Gewusst wie: Definieren und Ausführen von dynamischen MethodenHow to: Define and Execute Dynamic Methods

Die folgenden Verfahren zeigen, wie eine einfache dynamische Methode sowie eine dynamische Methode, die an eine Instanz einer Klasse gebunden ist, definiert und ausgeführt werden.The following procedures show how to define and execute a simple dynamic method and a dynamic method bound to an instance of a class. Weitere Informationen zu dynamischen Methoden finden Sie in der DynamicMethod-Klasse und unter Szenarios für die Reflektionsausgabe mit dynamischen Methoden.For more information on dynamic methods, see the DynamicMethod class and Reflection Emit Dynamic Method Scenarios.

So definieren und Sie eine dynamische Methode und führen diese ausTo define and execute a dynamic method

  1. Deklarieren Sie einen Delegattyp, um die Methode auszuführen.Declare a delegate type to execute the method. Erwägen Sie, einen generischen Delegaten zu verwenden, um die Anzahl der Delegattypen zu minimieren, die Sie benötigen.Consider using a generic delegate to minimize the number of delegate types you need to declare. Der folgende Code deklariert zwei Delegattypen, die für eine SquareIt-Methode verwendet werden könnt. Eine Methode davon ist generisch.The following code declares two delegate types that could be used for the SquareIt method, and one of them is generic.

    private: 
        delegate long long SquareItInvoker(int input);
    
        generic<typename TReturn, typename TParameter0> 
            delegate TReturn OneParameter(TParameter0 p0);
    
    private delegate long SquareItInvoker(int input);
    
    private delegate TReturn OneParameter<TReturn, TParameter0>
        (TParameter0 p0);
    
    Private Delegate Function _
        SquareItInvoker(ByVal input As Integer) As Long 
    
    Private Delegate Function _
        OneParameter(Of TReturn, TParameter0) _
        (ByVal p0 As TParameter0) As TReturn 
    
  2. Erstellen Sie ein Array, das die Parametertypen für die dynamische Methode angibt.Create an array that specifies the parameter types for the dynamic method. In diesem Beispiel ist der einzige Parameter ein int (Integer in Visual Basic), also verfügt das Array nur über ein Element.In this example, the only parameter is an int (Integer in Visual Basic), so the array has only one element.

    array<Type^>^ methodArgs = { int::typeid };
    
    Type[] methodArgs = {typeof(int)};
    
    Dim methodArgs As Type() = { GetType(Integer) }
    
  3. Erstellen Sie eine DynamicMethod.Create a DynamicMethod. In diesem Beispiel trägt die Methode die Bezeichnung SquareIt.In this example the method is named SquareIt.

    Hinweis

    Es ist nicht nötig, den dynamischen Methoden Namen zu geben. Sie können auch nicht nach Namen aufgerufen werden.It is not necessary to give dynamic methods names, and they cannot be invoked by name. Mehrere dynamische Methoden können über denselben Namen verfügen.Multiple dynamic methods can have the same name. Jedoch erscheint der Name in Aufruflisten und kann für das Debuggen hilfreich sein.However, the name appears in call stacks and can be useful for debugging.

    Der Typ des Rückgabewerts ist als long angegeben.The type of the return value is specified as long. Die Methode ist dem Modul zugeordnet, das die Example-Klasse besitzt, die den Beispielcode enthält.The method is associated with the module that contains the Example class, which contains the example code. Jedes geladene Modul kann angegeben werden.Any loaded module could be specified. Die dynamische Methode verhält sich wie eine static-Methode auf Modulebene (Shared in Visual Basic).The dynamic method acts like a module-level static method (Shared in Visual Basic).

    DynamicMethod^ squareIt = gcnew DynamicMethod(
        "SquareIt", 
        long long::typeid, 
        methodArgs, 
        Example::typeid->Module);
    
    DynamicMethod squareIt = new DynamicMethod(
        "SquareIt", 
        typeof(long), 
        methodArgs, 
        typeof(Example).Module);
    
    Dim squareIt As New DynamicMethod( _
        "SquareIt", _
        GetType(Long), _
        methodArgs, _
        GetType(Example).Module)
    
  4. Geben Sie den Methodentext aus.Emit the method body. In diesem Beispiel wird ein ILGenerator-Objekt zum Ausgeben der Microsoft Intermediate Language (MSIL) verwendet.In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL). Alternativ kann ein DynamicILInfo-Objekt in Kombination mit nicht verwalteten Codegeneratoren verwendet werden, um den Methodentext für eine DynamicMethod auszugeben.Alternatively, a DynamicILInfo object can be used in conjunction with unmanaged code generators to emit the method body for a DynamicMethod.

    Die MSIL lädt in diesem Beispiel das Argument (ein int) auf den Stapel, konvertiert es zu long, dupliziert long und multipliziert die zwei Zahlen.The MSIL in this example loads the argument, which is an int, onto the stack, converts it to a long, duplicates the long, and multiplies the two numbers. Dadurch verbleibt das quadratische Ergebnis im Stapel, und die Methode muss lediglich wieder zurückspringen.This leaves the squared result on the stack, and all the method has to do is return.

    ILGenerator^ il = squareIt->GetILGenerator();
    il->Emit(OpCodes::Ldarg_0);
    il->Emit(OpCodes::Conv_I8);
    il->Emit(OpCodes::Dup);
    il->Emit(OpCodes::Mul);
    il->Emit(OpCodes::Ret);
    
    ILGenerator il = squareIt.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Conv_I8);
    il.Emit(OpCodes.Dup);
    il.Emit(OpCodes.Mul);
    il.Emit(OpCodes.Ret);
    
    Dim il As ILGenerator = squareIt.GetILGenerator()
    il.Emit(OpCodes.Ldarg_0)
    il.Emit(OpCodes.Conv_I8)
    il.Emit(OpCodes.Dup)
    il.Emit(OpCodes.Mul)
    il.Emit(OpCodes.Ret)
    
  5. Erstellen Sie eine Instanz des Delegaten (in Schritt 1 deklariert), der die dynamische Methode durch Aufruf der CreateDelegate-Methode darstellt.Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate method. Durch die Erstellung des Delegaten wird die Methode abgeschlossen und alle weiteren Versuche, die Methode zu ändern, z.B. durch Hinzufügen weiterer MSIL, werden ignoriert.Creating the delegate completes the method, and any further attempts to change the method — for example, adding more MSIL — are ignored. Der folgende Code erstellt den Delegaten und ruft ihn mithilfe eines generischen Delegaten auf.The following code creates the delegate and invokes it, using a generic delegate.

    OneParameter<long long, int>^ invokeSquareIt = 
        (OneParameter<long long, int>^)
        squareIt->CreateDelegate(OneParameter<long long, int>::typeid);
    
    Console::WriteLine("123456789 squared = {0}",
        invokeSquareIt(123456789));
    
    OneParameter<long, int> invokeSquareIt = 
        (OneParameter<long, int>)
        squareIt.CreateDelegate(typeof(OneParameter<long, int>));
    
    Console.WriteLine("123456789 squared = {0}",
        invokeSquareIt(123456789));
    
    Dim invokeSquareIt As OneParameter(Of Long, Integer) = _
        CType( _
            squareIt.CreateDelegate( _
                GetType(OneParameter(Of Long, Integer))), _
            OneParameter(Of Long, Integer) _
        )
    
    Console.WriteLine("123456789 squared = {0}", _ 
        invokeSquareIt(123456789))
    

So definieren Sie eine dynamische Methode, die an ein Objekt gebunden ist, und führen sie ausTo define and execute a dynamic method that is bound to an object

  1. Deklarieren Sie einen Delegattyp, um die Methode auszuführen.Declare a delegate type to execute the method. Erwägen Sie, einen generischen Delegaten zu verwenden, um die Anzahl der Delegattypen zu minimieren, die Sie benötigen.Consider using a generic delegate to minimize the number of delegate types you need to declare. Der folgende Code deklariert einen generischen Delegattyp, der zum Ausführen einer beliebigen Methode mit einem Parameter oder Rückgabewert bzw. einer Methode mit zwei Parametern und einem Rückgabewert verwendet werden kann, falls der Delegat an ein Objekt gebunden ist.The following code declares a generic delegate type that can be used to execute any method with one parameter and a return value, or a method with two parameters and a return value if the delegate is bound to an object.

    generic<typename TReturn, typename TParameter0> 
        delegate TReturn OneParameter(TParameter0 p0);
    
    private delegate TReturn OneParameter<TReturn, TParameter0>
        (TParameter0 p0);
    
    Private Delegate Function _
        OneParameter(Of TReturn, TParameter0) _
        (ByVal p0 As TParameter0) As TReturn 
    
  2. Erstellen Sie ein Array, das die Parametertypen für die dynamische Methode angibt.Create an array that specifies the parameter types for the dynamic method. Wenn der Delegat, der die Methode darstellt, an ein Objekt gebunden ist, muss der erste Parameter mit dem Typ übereinstimmen, an den der Delegat gebunden ist.If the delegate representing the method is to be bound to an object, the first parameter must match the type the delegate is bound to. In diesem Beispiel gibt es zwei Parameter vom Typ Example und int (Integer in Visual Basic).In this example, there are two parameters, of type Example and type int (Integer in Visual Basic).

    array<Type^>^ methodArgs2 = { Example::typeid, int::typeid };
    
    Type[] methodArgs2 = { typeof(Example), typeof(int) };
    
    Dim methodArgs2 As Type() = _
        { GetType(Example), GetType(Integer) }
    
  3. Erstellen Sie eine DynamicMethod.Create a DynamicMethod. In diesem Beispiel hat die Methode keinen Namen.In this example the method has no name. Der Typ des Rückgabewerts ist als int (Integer in Visual Basic) angegeben.The type of the return value is specified as int (Integer in Visual Basic). Die Methode hat Zugriff auf die privaten und geschützten Member der Example-Klasse.The method has access to the private and protected members of the Example class.

    DynamicMethod^ multiplyHidden = gcnew DynamicMethod(
        "", 
        int::typeid, 
        methodArgs2, 
        Example::typeid);
    
    DynamicMethod multiplyHidden = new DynamicMethod(
        "", 
        typeof(int), 
        methodArgs2, 
        typeof(Example));
    
    Dim multiplyPrivate As New DynamicMethod( _
        "", _
        GetType(Integer), _
        methodArgs2, _
        GetType(Example))
    
  4. Geben Sie den Methodentext aus.Emit the method body. In diesem Beispiel wird ein ILGenerator-Objekt zum Ausgeben der Microsoft Intermediate Language (MSIL) verwendet.In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL). Alternativ kann ein DynamicILInfo-Objekt in Kombination mit nicht verwalteten Codegeneratoren verwendet werden, um den Methodentext für eine DynamicMethod auszugeben.Alternatively, a DynamicILInfo object can be used in conjunction with unmanaged code generators to emit the method body for a DynamicMethod.

    Die MSIL lädt in diesem Beispiel das erste Argument, welches eine Instanz der Example-Klasse ist, und verwendet es, um den Wert eines privaten Instanzenfelds vom Typ int zu laden.The MSIL in this example loads the first argument, which is an instance of the Example class, and uses it to load the value of a private instance field of type int. Das zweite Argument wird geladen, und zwei Zahlen werden multipliziert.The second argument is loaded, and the two numbers are multiplied. Wenn das Ergebnis größer als int ist, wird der Wert abgeschnitten und die wichtigsten Teile verworfen.If the result is larger than int, the value is truncated and the most significant bits are discarded. Die Methode springt zurück und der zurückzugebende Wert befindet sich auf dem Stapel.The method returns, with the return value on the stack.

    ILGenerator^ ilMH = multiplyHidden->GetILGenerator();
    ilMH->Emit(OpCodes::Ldarg_0);
    
    FieldInfo^ testInfo = Example::typeid->GetField("test",
        BindingFlags::NonPublic | BindingFlags::Instance);
    
    ilMH->Emit(OpCodes::Ldfld, testInfo);
    ilMH->Emit(OpCodes::Ldarg_1);
    ilMH->Emit(OpCodes::Mul);
    ilMH->Emit(OpCodes::Ret);
    
    ILGenerator ilMH = multiplyHidden.GetILGenerator();
    ilMH.Emit(OpCodes.Ldarg_0);
    
    FieldInfo testInfo = typeof(Example).GetField("test",
        BindingFlags.NonPublic | BindingFlags.Instance);
    
    ilMH.Emit(OpCodes.Ldfld, testInfo);
    ilMH.Emit(OpCodes.Ldarg_1);
    ilMH.Emit(OpCodes.Mul);
    ilMH.Emit(OpCodes.Ret);
    
    Dim ilMP As ILGenerator = multiplyPrivate.GetILGenerator()
    ilMP.Emit(OpCodes.Ldarg_0)
    
    Dim testInfo As FieldInfo = _
        GetType(Example).GetField("test", _
            BindingFlags.NonPublic Or BindingFlags.Instance)
    
    ilMP.Emit(OpCodes.Ldfld, testInfo)
    ilMP.Emit(OpCodes.Ldarg_1)
    ilMP.Emit(OpCodes.Mul)
    ilMP.Emit(OpCodes.Ret)
    
  5. Erstellen Sie eine Instanz des Delegaten (in Schritt 1 deklariert), der die dynamische Methode durch Aufruf der CreateDelegate(Type, Object)-Methodenüberladung darstellt.Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate(Type, Object) method overload. Durch die Erstellung des Delegaten wird die Methode abgeschlossen und alle weiteren Versuche, die Methode zu ändern, z.B. durch Hinzufügen weiterer MSIL, werden ignoriert.Creating the delegate completes the method, and any further attempts to change the method — for example, adding more MSIL — are ignored.

    Hinweis

    Sie können die CreateDelegate-Methode mehrfach aufrufen, um die Delegaten zu erstellen, die an andere Instanzen des Zieltyps gebunden sind.You can call the CreateDelegate method multiple times to create delegates bound to other instances of the target type.

    Der folgende Code bindet die Methode an eine neue Instanz der Example-Klasse, deren privates Testfeld auf 42 festgelegt ist.The following code binds the method to a new instance of the Example class whose private test field is set to 42. Das heißt, dass jedes Mal, wenn der Delegat aufgerufen wird, die Instanz von Example an den ersten Parameter der Methode übergeben wird.That is, each time the delegate is invoked the instance of Example is passed to the first parameter of the method.

    Der Delegat OneParameter wird verwendet, da der erste Parameter der Methode immer die Instanz von Example erhält.The delegate OneParameter is used because the first parameter of the method always receives the instance of Example. Wenn der Delegat aufgerufen wird, ist nur der zweite Parameter erforderlich.When the delegate is invoked, only the second parameter is required.

    OneParameter<int, int>^ invoke = (OneParameter<int, int>^)
        multiplyHidden->CreateDelegate(
            OneParameter<int, int>::typeid, 
            gcnew Example(42)
        );
    
    Console::WriteLine("3 * test = {0}", invoke(3));
    
    OneParameter<int, int> invoke = (OneParameter<int, int>)
        multiplyHidden.CreateDelegate(
            typeof(OneParameter<int, int>), 
            new Example(42)
        );
    
    Console.WriteLine("3 * test = {0}", invoke(3));
    
    Dim invoke As OneParameter(Of Integer, Integer) = _
        CType( _
            multiplyPrivate.CreateDelegate( _
                GetType(OneParameter(Of Integer, Integer)), _
                new Example(42) _
            ), _
            OneParameter(Of Integer, Integer) _
        )
    
    Console.WriteLine("3 * test = {0}", invoke(3))
    

BeispielExample

Das folgende Codebeispiel zeigt eine einfache dynamische Methode sowie eine dynamische Methode, die an eine Instanz einer Klasse gebunden ist.The following code example demonstrates a simple dynamic method and a dynamic method bound to an instance of a class.

Die einfache dynamische Methode nimmt ein Argument, einen 32-Bit-Integer und gibt das 64-Bit-Quadrat dieses Integers zurück.The simple dynamic method takes one argument, a 32-bit integer, and returns the 64-bit square of that integer. Ein generischer Delegat wird zum Aufrufen der Methode verwendet.A generic delegate is used to invoke the method.

Die zweite dynamische Methode hat zwei Parameter des Typs Example und int (Integer in Visual Basic).The second dynamic method has two parameters, of type Example and type int (Integer in Visual Basic). Wenn die dynamische Methode erstellt wurde, wird sie mithilfe eines generischen Delegaten, der ein Argument vom Typ int besitzt, an eine Instanz von Example gebunden.When the dynamic method has been created, it is bound to an instance of Example, using a generic delegate that has one argument of type int. Der Delegat besitzt kein Argument vom Typ Example, da der erste Parameter der Methode immer die gebundene Instanz von Example erhält.The delegate does not have an argument of type Example because the first parameter of the method always receives the bound instance of Example. Wenn der Delegat aufgerufen wird, wird nur das int-Argument bereitgestellt.When the delegate is invoked, only the int argument is supplied. Diese dynamische Methode greift auf ein privates Feld der Example-Klasse zu und gibt das Produkt des privaten Felds und das int-Argument zurück.This dynamic method accesses a private field of the Example class and returns the product of the private field and the int argument.

Das Codebeispiel definiert Delegaten, die zum Ausführen dieser Methoden verwendet werden können.The code example defines delegates that can be used to execute the methods.

using namespace System;
using namespace System::Reflection;
using namespace System::Reflection::Emit;

public ref class Example
{
    // The following constructor and private field are used to
    // demonstrate a method bound to an object.
private:
    int test;
    
public:
    Example(int test) { this->test = test; }

    // Declare delegates that can be used to execute the completed 
    // SquareIt dynamic method. The OneParameter delegate can be 
    // used to execute any method with one parameter and a return
    // value, or a method with two parameters and a return value
    // if the delegate is bound to an object.
    //
private: 
    delegate long long SquareItInvoker(int input);

    generic<typename TReturn, typename TParameter0> 
        delegate TReturn OneParameter(TParameter0 p0);

public:
    static void Main()
    {
        // Example 1: A simple dynamic method.
        //
        // Create an array that specifies the parameter types for the
        // dynamic method. In this example the only parameter is an 
        // int, so the array has only one element.
        //
        array<Type^>^ methodArgs = { int::typeid };

        // Create a DynamicMethod. In this example the method is
        // named SquareIt. It is not necessary to give dynamic 
        // methods names. They cannot be invoked by name, and two
        // dynamic methods can have the same name. However, the 
        // name appears in calls stacks and can be useful for
        // debugging. 
        //
        // In this example the return type of the dynamic method is
        // long long. The method is associated with the module that 
        // contains the Example class. Any loaded module could be
        // specified. The dynamic method is like a module-level
        // static method.
        //
        DynamicMethod^ squareIt = gcnew DynamicMethod(
            "SquareIt", 
            long long::typeid, 
            methodArgs, 
            Example::typeid->Module);

        // Emit the method body. In this example ILGenerator is used
        // to emit the MSIL. DynamicMethod has an associated type
        // DynamicILInfo that can be used in conjunction with 
        // unmanaged code generators.
        //
        // The MSIL loads the argument, which is an int, onto the 
        // stack, converts the int to a long long, duplicates the top
        // item on the stack, and multiplies the top two items on the
        // stack. This leaves the squared number on the stack, and 
        // all the method has to do is return.
        //
        ILGenerator^ il = squareIt->GetILGenerator();
        il->Emit(OpCodes::Ldarg_0);
        il->Emit(OpCodes::Conv_I8);
        il->Emit(OpCodes::Dup);
        il->Emit(OpCodes::Mul);
        il->Emit(OpCodes::Ret);

        // Create a delegate that represents the dynamic method. 
        // Creating the delegate completes the method, and any further 
        // attempts to change the method (for example, by adding more
        // MSIL) are ignored. The following code uses a generic 
        // delegate that can produce delegate types matching any
        // single-parameter method that has a return type.
        //
        OneParameter<long long, int>^ invokeSquareIt = 
            (OneParameter<long long, int>^)
            squareIt->CreateDelegate(OneParameter<long long, int>::typeid);

        Console::WriteLine("123456789 squared = {0}",
            invokeSquareIt(123456789));

        // Example 2: A dynamic method bound to an instance.
        //
        // Create an array that specifies the parameter types for a
        // dynamic method. If the delegate representing the method
        // is to be bound to an object, the first parameter must 
        // match the type the delegate is bound to. In the following
        // code the bound instance is of the Example class. 
        //
        array<Type^>^ methodArgs2 = { Example::typeid, int::typeid };

        // Create a DynamicMethod. In this example the method has no
        // name. The return type of the method is int. The method 
        // has access to the protected and private data of the 
        // Example class.
        //
        DynamicMethod^ multiplyHidden = gcnew DynamicMethod(
            "", 
            int::typeid, 
            methodArgs2, 
            Example::typeid);

        // Emit the method body. In this example ILGenerator is used
        // to emit the MSIL. DynamicMethod has an associated type
        // DynamicILInfo that can be used in conjunction with 
        // unmanaged code generators.
        //
        // The MSIL loads the first argument, which is an instance of
        // the Example class, and uses it to load the value of a 
        // private instance field of type int. The second argument is
        // loaded, and the two numbers are multiplied. If the result
        // is larger than int, the value is truncated and the most 
        // significant bits are discarded. The method returns, with
        // the return value on the stack.
        //
        ILGenerator^ ilMH = multiplyHidden->GetILGenerator();
        ilMH->Emit(OpCodes::Ldarg_0);

        FieldInfo^ testInfo = Example::typeid->GetField("test",
            BindingFlags::NonPublic | BindingFlags::Instance);

        ilMH->Emit(OpCodes::Ldfld, testInfo);
        ilMH->Emit(OpCodes::Ldarg_1);
        ilMH->Emit(OpCodes::Mul);
        ilMH->Emit(OpCodes::Ret);

        // Create a delegate that represents the dynamic method. 
        // Creating the delegate completes the method, and any further 
        // attempts to change the method � for example, by adding more
        // MSIL � are ignored. 
        // 
        // The following code binds the method to a new instance
        // of the Example class whose private test field is set to 42.
        // That is, each time the delegate is invoked the instance of
        // Example is passed to the first parameter of the method.
        //
        // The delegate OneParameter is used, because the first
        // parameter of the method receives the instance of Example.
        // When the delegate is invoked, only the second parameter is
        // required. 
        //
        OneParameter<int, int>^ invoke = (OneParameter<int, int>^)
            multiplyHidden->CreateDelegate(
                OneParameter<int, int>::typeid, 
                gcnew Example(42)
            );

        Console::WriteLine("3 * test = {0}", invoke(3));
    }
};

void main()
{
    Example::Main();
}
/* This code example produces the following output:

123456789 squared = 15241578750190521
3 * test = 126
 */
using System;
using System.Reflection;
using System.Reflection.Emit;

public class Example
{
    // The following constructor and private field are used to
    // demonstrate a method bound to an object.
    private int test;
    public Example(int test) { this.test = test; }

    // Declare delegates that can be used to execute the completed 
    // SquareIt dynamic method. The OneParameter delegate can be 
    // used to execute any method with one parameter and a return
    // value, or a method with two parameters and a return value
    // if the delegate is bound to an object.
    //
    private delegate long SquareItInvoker(int input);

    private delegate TReturn OneParameter<TReturn, TParameter0>
        (TParameter0 p0);

    public static void Main()
    {
        // Example 1: A simple dynamic method.
        //
        // Create an array that specifies the parameter types for the
        // dynamic method. In this example the only parameter is an 
        // int, so the array has only one element.
        //
        Type[] methodArgs = {typeof(int)};

        // Create a DynamicMethod. In this example the method is
        // named SquareIt. It is not necessary to give dynamic 
        // methods names. They cannot be invoked by name, and two
        // dynamic methods can have the same name. However, the 
        // name appears in calls stacks and can be useful for
        // debugging. 
        //
        // In this example the return type of the dynamic method
        // is long. The method is associated with the module that 
        // contains the Example class. Any loaded module could be
        // specified. The dynamic method is like a module-level
        // static method.
        //
        DynamicMethod squareIt = new DynamicMethod(
            "SquareIt", 
            typeof(long), 
            methodArgs, 
            typeof(Example).Module);

        // Emit the method body. In this example ILGenerator is used
        // to emit the MSIL. DynamicMethod has an associated type
        // DynamicILInfo that can be used in conjunction with 
        // unmanaged code generators.
        //
        // The MSIL loads the argument, which is an int, onto the 
        // stack, converts the int to a long, duplicates the top
        // item on the stack, and multiplies the top two items on the
        // stack. This leaves the squared number on the stack, and 
        // all the method has to do is return.
        //
        ILGenerator il = squareIt.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Conv_I8);
        il.Emit(OpCodes.Dup);
        il.Emit(OpCodes.Mul);
        il.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method. 
        // Creating the delegate completes the method, and any further 
        // attempts to change the method (for example, by adding more
        // MSIL) are ignored. The following code uses a generic 
        // delegate that can produce delegate types matching any
        // single-parameter method that has a return type.
        //
        OneParameter<long, int> invokeSquareIt = 
            (OneParameter<long, int>)
            squareIt.CreateDelegate(typeof(OneParameter<long, int>));

        Console.WriteLine("123456789 squared = {0}",
            invokeSquareIt(123456789));

        // Example 2: A dynamic method bound to an instance.
        //
        // Create an array that specifies the parameter types for a
        // dynamic method. If the delegate representing the method
        // is to be bound to an object, the first parameter must 
        // match the type the delegate is bound to. In the following
        // code the bound instance is of the Example class. 
        //
        Type[] methodArgs2 = { typeof(Example), typeof(int) };

        // Create a DynamicMethod. In this example the method has no
        // name. The return type of the method is int. The method 
        // has access to the protected and private data of the 
        // Example class.
        //
        DynamicMethod multiplyHidden = new DynamicMethod(
            "", 
            typeof(int), 
            methodArgs2, 
            typeof(Example));

        // Emit the method body. In this example ILGenerator is used
        // to emit the MSIL. DynamicMethod has an associated type
        // DynamicILInfo that can be used in conjunction with 
        // unmanaged code generators.
        //
        // The MSIL loads the first argument, which is an instance of
        // the Example class, and uses it to load the value of a 
        // private instance field of type int. The second argument is
        // loaded, and the two numbers are multiplied. If the result
        // is larger than int, the value is truncated and the most 
        // significant bits are discarded. The method returns, with
        // the return value on the stack.
        //
        ILGenerator ilMH = multiplyHidden.GetILGenerator();
        ilMH.Emit(OpCodes.Ldarg_0);

        FieldInfo testInfo = typeof(Example).GetField("test",
            BindingFlags.NonPublic | BindingFlags.Instance);

        ilMH.Emit(OpCodes.Ldfld, testInfo);
        ilMH.Emit(OpCodes.Ldarg_1);
        ilMH.Emit(OpCodes.Mul);
        ilMH.Emit(OpCodes.Ret);

        // Create a delegate that represents the dynamic method. 
        // Creating the delegate completes the method, and any further 
        // attempts to change the method — for example, by adding more
        // MSIL — are ignored. 
        // 
        // The following code binds the method to a new instance
        // of the Example class whose private test field is set to 42.
        // That is, each time the delegate is invoked the instance of
        // Example is passed to the first parameter of the method.
        //
        // The delegate OneParameter is used, because the first
        // parameter of the method receives the instance of Example.
        // When the delegate is invoked, only the second parameter is
        // required. 
        //
        OneParameter<int, int> invoke = (OneParameter<int, int>)
            multiplyHidden.CreateDelegate(
                typeof(OneParameter<int, int>), 
                new Example(42)
            );

        Console.WriteLine("3 * test = {0}", invoke(3));
    }
}
/* This code example produces the following output:

123456789 squared = 15241578750190521
3 * test = 126
 */
Imports System.Reflection
Imports System.Reflection.Emit

Public Class Example

    ' The following constructor and private field are used to
    ' demonstrate a method bound to an object.
    '
    Private test As Integer
    Public Sub New(ByVal test As Integer) 
        Me.test = test 
    End Sub
    
    ' Declare delegates that can be used to execute the completed 
    ' SquareIt dynamic method. The OneParameter delegate can be 
    ' used to execute any method with one parameter and a return
    ' value, or a method with two parameters and a return value
    ' if the delegate is bound to an object.
    '
    Private Delegate Function _
        SquareItInvoker(ByVal input As Integer) As Long 
    
    Private Delegate Function _
        OneParameter(Of TReturn, TParameter0) _
        (ByVal p0 As TParameter0) As TReturn 

    Public Shared Sub Main() 

        ' Example 1: A simple dynamic method.
        '
        ' Create an array that specifies the parameter types for the
        ' dynamic method. In this example the only parameter is an 
        ' Integer, so the array has only one element.
        '
        Dim methodArgs As Type() = { GetType(Integer) }

        ' Create a DynamicMethod. In this example the method is
        ' named SquareIt. It is not necessary to give dynamic 
        ' methods names. They cannot be invoked by name, and two
        ' dynamic methods can have the same name. However, the 
        ' name appears in calls stacks and can be useful for
        ' debugging. 
        '
        ' In this example the return type of the dynamic method
        ' is Long. The method is associated with the module that 
        ' contains the Example class. Any loaded module could be
        ' specified. The dynamic method is like a module-level
        ' Shared method.
        '
        Dim squareIt As New DynamicMethod( _
            "SquareIt", _
            GetType(Long), _
            methodArgs, _
            GetType(Example).Module)

        ' Emit the method body. In this example ILGenerator is used
        ' to emit the MSIL. DynamicMethod has an associated type
        ' DynamicILInfo that can be used in conjunction with 
        ' unmanaged code generators.
        '
        ' The MSIL loads the argument, which is an Integer, onto the 
        ' stack, converts the Integer to a Long, duplicates the top
        ' item on the stack, and multiplies the top two items on the
        ' stack. This leaves the squared number on the stack, and 
        ' all the method has to do is return.
        '
        Dim il As ILGenerator = squareIt.GetILGenerator()
        il.Emit(OpCodes.Ldarg_0)
        il.Emit(OpCodes.Conv_I8)
        il.Emit(OpCodes.Dup)
        il.Emit(OpCodes.Mul)
        il.Emit(OpCodes.Ret)

        ' Create a delegate that represents the dynamic method. 
        ' Creating the delegate completes the method, and any further 
        ' attempts to change the method (for example, by adding more
        ' MSIL) are ignored. The following code uses a generic 
        ' delegate that can produce delegate types matching any
        ' single-parameter method that has a return type.
        '
        Dim invokeSquareIt As OneParameter(Of Long, Integer) = _
            CType( _
                squareIt.CreateDelegate( _
                    GetType(OneParameter(Of Long, Integer))), _
                OneParameter(Of Long, Integer) _
            )
        
        Console.WriteLine("123456789 squared = {0}", _ 
            invokeSquareIt(123456789))


        ' Example 2: A dynamic method bound to an instance.
        '
        ' Create an array that specifies the parameter types for a
        ' dynamic method. If the delegate representing the method
        ' is to be bound to an object, the first parameter must 
        ' match the type the delegate is bound to. In the following
        ' code the bound instance is of the Example class. 
        '
        Dim methodArgs2 As Type() = _
            { GetType(Example), GetType(Integer) }

        ' Create a DynamicMethod. In this example the method has no
        ' name. The return type of the method is Integer. The method 
        ' has access to the protected and private members of the 
        ' Example class. 
        '
        Dim multiplyPrivate As New DynamicMethod( _
            "", _
            GetType(Integer), _
            methodArgs2, _
            GetType(Example))

        ' Emit the method body. In this example ILGenerator is used
        ' to emit the MSIL. DynamicMethod has an associated type
        ' DynamicILInfo that can be used in conjunction with 
        ' unmanaged code generators.
        '
        ' The MSIL loads the first argument, which is an instance of
        ' the Example class, and uses it to load the value of a 
        ' private instance field of type Integer. The second argument 
        ' is loaded, and the two numbers are multiplied. If the result
        ' is larger than Integer, the value is truncated and the most 
        ' significant bits are discarded. The method returns, with
        ' the return value on the stack.
        '
        Dim ilMP As ILGenerator = multiplyPrivate.GetILGenerator()
        ilMP.Emit(OpCodes.Ldarg_0)
        
        Dim testInfo As FieldInfo = _
            GetType(Example).GetField("test", _
                BindingFlags.NonPublic Or BindingFlags.Instance)

        ilMP.Emit(OpCodes.Ldfld, testInfo)
        ilMP.Emit(OpCodes.Ldarg_1)
        ilMP.Emit(OpCodes.Mul)
        ilMP.Emit(OpCodes.Ret)

        ' Create a delegate that represents the dynamic method. 
        ' Creating the delegate completes the method, and any further 
        ' attempts to change the method  for example, by adding more
        ' MSIL  are ignored. 
        ' 
        ' The following code binds the method to a new instance
        ' of the Example class whose private test field is set to 42.
        ' That is, each time the delegate is invoked the instance of
        ' Example is passed to the first parameter of the method.
        '
        ' The delegate OneParameter is used, because the first
        ' parameter of the method receives the instance of Example.
        ' When the delegate is invoked, only the second parameter is
        ' required. 
        '
        Dim invoke As OneParameter(Of Integer, Integer) = _
            CType( _
                multiplyPrivate.CreateDelegate( _
                    GetType(OneParameter(Of Integer, Integer)), _
                    new Example(42) _
                ), _
                OneParameter(Of Integer, Integer) _
            )
        
        Console.WriteLine("3 * test = {0}", invoke(3))

    End Sub 

End Class

' This code example produces the following output:
'
'123456789 squared = 15241578750190521
'3 * test = 126
' 

Siehe auchSee also