方法: 動的メソッドを定義して実行する
次の手順では、単純な動的メソッドと、クラスのインスタンスにバインドされた動的メソッドを定義して実行する方法を示します。 動的メソッドの詳細については、 DynamicMethod クラスを参照してください。
メソッドを実行するデリゲート型を宣言します。 ジェネリック デリゲートを使用して、宣言する必要があるデリゲート型の数を最小限にすることを検討してください。 次のコードでは、
SquareIt
メソッドに使用できる 2 つのデリゲート型を宣言しています。そのうちの 1 つはジェネリックです。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
動的メソッドのパラメーター型を指定する配列を作成します。 この例では、唯一のパラメーターは
int
(Visual Basic ではInteger
) であるため、配列には要素が 1 つだけ含まれます。array<Type^>^ methodArgs = { int::typeid };
Type[] methodArgs = {typeof(int)};
Dim methodArgs As Type() = {GetType(Integer)}
DynamicMethodを作成します。 この例では、メソッドの名前は
SquareIt
です。注
動的メソッド名を指定する必要はありません。また、名前で呼び出すことはできません。 複数の動的メソッドに同じ名前を付けることができます。 ただし、名前は呼び出し履歴に表示され、デバッグに役立ちます。
戻り値の型は、
long
として指定されます。 メソッドは、コード例を含むExample
クラスを含むモジュールに関連付けられています。 読み込まれたモジュールを指定できます。 動的メソッドは、モジュール レベルのstatic
メソッドのように動作します (Visual Basic ではShared
)。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)
メソッド本体を出力します。 この例では、 ILGenerator オブジェクトを使用して共通の中間言語 (CIL) を出力します。 または、 DynamicILInfo オブジェクトをアンマネージ コード ジェネレーターと組み合わせて使用して、 DynamicMethodのメソッド本体を出力することもできます。
この例の CIL は、引数 (
int
) をスタックに読み込み、それをlong
に変換し、long
を複製して、2 つの数値を乗算します。 これにより、2乗の結果がスタックに残り、メソッドはそれを返すだけで済みます。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)
CreateDelegate メソッドを呼び出して動的メソッドを表すデリゲート (手順 1 で宣言) のインスタンスを作成します。 デリゲートを作成するとメソッドが完了し、メソッドをさらに変更しようとする試み (CIL の追加など) は無視されます。 次のコードは、汎用デリゲートを使用してデリゲートを作成し、それを呼び出します。
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 = {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))
メソッドを実行するデリゲート型を宣言します。 ジェネリック デリゲートを使用して、宣言する必要があるデリゲート型の数を最小限にすることを検討してください。 次のコードでは、1 つのパラメーターと戻り値を持つ任意のメソッドを実行するために使用できるジェネリック デリゲート型を宣言します。デリゲートがオブジェクトにバインドされている場合は、2 つのパラメーターと戻り値を持つメソッドを宣言します。
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
動的メソッドのパラメーター型を指定する配列を作成します。 メソッドを表すデリゲートをオブジェクトにバインドする場合、最初のパラメーターはデリゲートのバインド先の型と一致する必要があります。 この例では、
Example
型とint
型 (Visual Basic ではInteger
) の 2 つのパラメーターがあります。array<Type^>^ methodArgs2 = { Example::typeid, int::typeid };
Type[] methodArgs2 = { typeof(Example), typeof(int) };
Dim methodArgs2 As Type() = _ {GetType(Example), GetType(Integer)}
DynamicMethodを作成します。 この例では、メソッドには名前がありません。 戻り値の型は、
int
として指定されます (Visual Basic ではInteger
)。 このメソッドは、Example
クラスのプライベート メンバーと保護されたメンバーにアクセスできます。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))
メソッド本体を出力します。 この例では、 ILGenerator オブジェクトを使用して共通の中間言語 (CIL) を出力します。 または、 DynamicILInfo オブジェクトをアンマネージ コード ジェネレーターと組み合わせて使用して、 DynamicMethodのメソッド本体を出力することもできます。
この例の CIL は、
Example
クラスのインスタンスである最初の引数を読み込み、それを使用してint
型のプライベート インスタンス フィールドの値を読み込みます。 2 番目の引数が読み込まれ、2 つの数値が乗算されます。 結果がint
より大きい場合、値は切り捨てられ、最上位ビットは破棄されます。 このメソッドは、スタック上の戻り値を使用して戻り値を返します。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)
CreateDelegate(Type, Object) メソッドオーバーロードを呼び出して動的メソッドを表すデリゲートのインスタンス (手順 1 で宣言) を作成します。 デリゲートを作成するとメソッドが完了し、メソッドをさらに変更しようとする試み (CIL の追加など) は無視されます。
注
CreateDelegate メソッドを複数回呼び出して、ターゲット型の他のインスタンスにバインドされたデリゲートを作成できます。
次のコードは、プライベート テスト フィールドが 42 に設定されている
Example
クラスの新しいインスタンスにメソッドをバインドします。 つまり、デリゲートが呼び出されるたびに、Example
のインスタンスがメソッドの最初のパラメーターに渡されます。メソッドの最初のパラメーターは常に
Example
のインスタンスを受け取るため、デリゲートOneParameter
が使用されます。 デリゲートが呼び出されると、2 番目のパラメーターのみが必要です。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 = {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))
例
次のコード例は、単純な動的メソッドと、クラスのインスタンスにバインドされた動的メソッドを示しています。
単純な動的メソッドは、1 つの引数 (32 ビット整数) を受け取り、その整数の 64 ビット 2 乗を返します。 ジェネリック デリゲートは、メソッドを呼び出すために使用されます。
2 番目の動的メソッドには、 Example
型と int
型 (Visual Basic のInteger
) の 2 つのパラメーターがあります。 動的メソッドが作成されると、int
型の 1 つの引数を持つジェネリック デリゲートを使用して、Example
のインスタンスにバインドされます。 メソッドの最初のパラメーターは常にExample
のバインドされたインスタンスを受け取るため、デリゲートはExample
型の引数を持っていません。 デリゲートが呼び出されると、 int
引数のみが指定されます。 この動的メソッドは、 Example
クラスのプライベート フィールドにアクセスし、プライベート フィールドと int
引数の積を返します。
このコード例では、メソッドの実行に使用できるデリゲートを定義します。
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 = {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 = {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
'
こちらもご覧ください
.NET