方法: 動的メソッドを定義および実行するHow to: Define and Execute Dynamic Methods

ここでは、単純な動的メソッドと、クラスのインスタンスにバインドされた動的メソッドを定義し、実行する手順について説明します。The following procedures show how to define and execute a simple dynamic method and a dynamic method bound to an instance of a class. 動的メソッドの詳細については、DynamicMethod クラスに関するトピックと「Reflection Emit Dynamic Method Scenarios」(リフレクション出力による動的メソッドのシナリオ) を参照してください。For more information on dynamic methods, see the DynamicMethod class and Reflection Emit Dynamic Method Scenarios.

動的メソッドを定義および実行するにはTo define and execute a dynamic method

  1. メソッドを実行するために、デリゲート型を宣言します。Declare a delegate type to execute the method. 汎用デリゲートを使用して、宣言する必要のあるデリゲート型の数を最小限に抑えるよう考慮してください。Consider using a generic delegate to minimize the number of delegate types you need to declare. 次のコードでは、SquareIt メソッドで使用できる 2 つのデリゲート型 (1 つはジェネリック) を宣言します。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. 動的メソッドのパラメーターの型を指定する配列を作成します。Create an array that specifies the parameter types for the dynamic method. この例では、唯一のパラメーターが int (Visual Basic では Integer) であるため、配列には要素は 1 つしかありません。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. DynamicMethod を作成します。Create a DynamicMethod. この例では、メソッドの名前は SquareIt です。In this example the method is named SquareIt.

    注意

    動的メソッドに名前を付ける必要はありません。動的メソッドは名前で呼び出すことはできません。It is not necessary to give dynamic methods names, and they cannot be invoked by name. 複数の動的メソッドに同じ名前を付けることができます。Multiple dynamic methods can have the same name. ただし、名前は呼び出し履歴に表示されるため、デバッグの際に役立つことがあります。However, the name appears in call stacks and can be useful for debugging.

    戻り値の型は、long として指定します。The type of the return value is specified as long. プログラム例を格納する Example クラスを含むモジュールにメソッドを関連付けます。The method is associated with the module that contains the Example class, which contains the example code. 読み込むモジュールを指定できます。Any loaded module could be specified. 動的メソッドは、モジュール レベルの static メソッド (Visual Basic では Shared) と同様に機能します。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. メソッド本体を出力します。Emit the method body. この例では、ILGenerator オブジェクトを使用して、MSIL (Microsoft Intermediate Language) を出力します。In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL). また、DynamicILInfo オブジェクトをアンマネージ コード ジェネレーターと組み合わせて使用して、DynamicMethod のメソッド本体を出力することもできます。Alternatively, a DynamicILInfo object can be used in conjunction with unmanaged code generators to emit the method body for a DynamicMethod.

    この例の MSIL は、int である引数をスタックに読み込み、これを long に変換します。次に、long を複製し、2 つの数値を乗算します。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. これにより、スタックには 2 乗された結果が残され、メソッドで実行する必要のあるすべてが返されます。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. CreateDelegate メソッドを呼び出して、動的メソッドを表す (手順 1 で宣言した) デリゲートのインスタンスを作成します。Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate method. デリゲートを作成すると、メソッドは完了します。メソッドにそれ以上変更を加えようとしても (MSIL の追加など) 無視されます。Creating the delegate completes the method, and any further attempts to change the method — for example, adding more MSIL — are ignored. 次のコードでは、汎用デリゲートを使用して、デリゲートを作成し呼び出します。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))
    

オブジェクトにバインドされた動的メソッドを定義および実行するにはTo define and execute a dynamic method that is bound to an object

  1. メソッドを実行するために、デリゲート型を宣言します。Declare a delegate type to execute the method. 汎用デリゲートを使用して、宣言する必要のあるデリゲート型の数を最小限に抑えるよう考慮してください。Consider using a generic delegate to minimize the number of delegate types you need to declare. 次のコードでは、1 つのパラメーターと戻り値を持つ任意のメソッド、またはデリゲートがオブジェクトにバインドされている場合は 2 つのパラメーターと戻り値を持つメソッドの実行に使用できる汎用デリゲート型を宣言します。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. 動的メソッドのパラメーターの型を指定する配列を作成します。Create an array that specifies the parameter types for the dynamic method. メソッドを表すデリゲートをオブジェクトにバインドする場合、1 つ目のパラメーターは、デリゲートのバインド先となる型と一致する必要があります。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. この例では、Example 型と int 型 (Visual Basic では Integer) の 2 つのパラメーターがあります。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. DynamicMethod を作成します。Create a DynamicMethod. この例では、メソッドに名前はありません。In this example the method has no name. 戻り値の型は、int (Visual Basic では Integer) として指定します。The type of the return value is specified as int (Integer in Visual Basic). このメソッドは、Example クラスのプライベート メンバーとプロテクト メンバーにアクセスできます。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. メソッド本体を出力します。Emit the method body. この例では、ILGenerator オブジェクトを使用して、MSIL (Microsoft Intermediate Language) を出力します。In this example, an ILGenerator object is used to emit the Microsoft intermediate language (MSIL). また、DynamicILInfo オブジェクトをアンマネージ コード ジェネレーターと組み合わせて使用して、DynamicMethod のメソッド本体を出力することもできます。Alternatively, a DynamicILInfo object can be used in conjunction with unmanaged code generators to emit the method body for a DynamicMethod.

    この例の MSIL は、Example クラスのインスタンスである 1 つ目の引数を読み込み、この引数を使用して、int 型のプライベート インスタンス フィールドの値を読み込みます。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. 2 つ目の引数が読み込まれ、この 2 つの数値が乗算されます。The second argument is loaded, and the two numbers are multiplied. この結果が int よりも大きい場合、値は切り捨てられ、最上位ビットは破棄されます。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);
    
    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. CreateDelegate(Type, Object) メソッド オーバーロードを呼び出して、動的メソッドを表す (手順 1 で宣言した) デリゲートのインスタンスを作成します。Create an instance of the delegate (declared in step 1) that represents the dynamic method by calling the CreateDelegate(Type, Object) method overload. デリゲートを作成すると、メソッドは完了します。メソッドにそれ以上変更を加えようとしても (MSIL の追加など) 無視されます。Creating the delegate completes the method, and any further attempts to change the method — for example, adding more MSIL — are ignored.

    注意

    CreateDelegate メソッドを複数回呼び出して、対象の型の他のインスタンスにバインドされたデリゲートを作成できます。You can call the CreateDelegate method multiple times to create delegates bound to other instances of the target type.

    次のコードでは、プライベート テスト フィールドが 42 に設定された Example クラスの新しいインスタンスにメソッドをバインドします。The following code binds the method to a new instance of the Example class whose private test field is set to 42. つまり、デリゲートが呼び出されるたびに、Example のインスタンスがメソッドの 1 つ目のパラメーターに渡されます。That is, each time the delegate is invoked the instance of Example is passed to the first parameter of the method.

    メソッドの 1 つ目のパラメーターは、常に Example のインスタンスを受け取るため、OneParameter デリゲートが使用されます。The delegate OneParameter is used because the first parameter of the method always receives the instance of Example. デリゲートの呼び出し時には、2 つ目のパラメーターだけが必要となります。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))
    

Example

単純な動的メソッドおよびクラスのインスタンスにバインドされた動的メソッドを次のコード例に示します。The following code example demonstrates a simple dynamic method and a dynamic method bound to an instance of a class.

この単純な動的メソッドは、32 ビット整数である引数を 1 つ受け取り、その整数の 2 乗を 64 ビットで返します。The simple dynamic method takes one argument, a 32-bit integer, and returns the 64-bit square of that integer. 汎用デリゲートを使用して、メソッドを呼び出します。A generic delegate is used to invoke the method.

2 つ目の動的メソッドには、Example 型と int 型 (Visual Basic では Integer) の 2 つのパラメーターがあります。The second dynamic method has two parameters, of type Example and type int (Integer in Visual Basic). 動的メソッドが作成されると、int 型の引数を 1 つ持つ汎用デリゲートを使用して、Example のインスタンスにバインドされます。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. メソッドの 1 つ目のパラメーターは、常に Example のバインドされたインスタンスを受け取るため、デリゲートは Example 型の引数を持ちません。The delegate does not have an argument of type Example because the first parameter of the method always receives the bound instance of Example. デリゲートの呼び出し時には、int 型の引数だけが提供されます。When the delegate is invoked, only the int argument is supplied. 動的メソッドは、Example クラスのプライベート フィールドにアクセスし、プライベート フィールドと int 型の引数の積を返します。This dynamic method accesses a private field of the Example class and returns the product of the private field and the int argument.

メソッドの実行に使用できるデリゲートを定義するコード例を次に示します。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
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
' 

関連項目See also