방법: 동적 메서드 정의 및 실행
다음 절차에서는 간단한 동적 메서드 및 클래스 인스턴스에 바인딩된 동적 메서드를 정의하고 실행하는 방법을 보여 줍니다. 동적 메서드에 대한 자세한 내용은 클래스를 참조하세요 DynamicMethod .
메서드를 실행할 대리자 형식을 선언합니다. 제네릭 대리자를 사용하여 선언해야 하는 대리자 형식 수를 최소화하는 것이 좋습니다. 다음 코드는
SquareIt
메서드에 사용할 수 있는 두 개의 대리자 형식을 선언하며, 둘 중 하나는 제네릭입니다.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
)이므로 배열에 요소가 하나만 있습니다.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
하고, 두 숫자를 곱합니다. 이렇게 하면 스택의 거듭제곱 결과가 구해지며, 메서드가 반환하기만 하면 됩니다.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 = {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))
메서드를 실행할 대리자 형식을 선언합니다. 제네릭 대리자를 사용하여 선언해야 하는 대리자 형식 수를 최소화하는 것이 좋습니다. 다음 코드는 매개 변수 하나가 있는 메서드 및 대리자가 개체에 바인딩된 경우 매개 변수 두 개와 반환 값이 있는 메서드를 실행하는 데 사용할 수 있는 제네릭 대리자 형식을 선언합니다.
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
) 형식의 두 매개 변수가 있습니다.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
클래스의 private 및 protected 멤버에 액세스할 수 있습니다.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
의 프라이빗 인스턴스 필드 값을 로드합니다. 두 번째 인수가 로드되고, 두 개의 숫자를 곱합니다. 결과가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 메서드를 여러 번 호출하여 대상 형식의 다른 인스턴스에 바인딩된 대리자를 만들 수 있습니다.
다음 코드는 private 테스트 필드가 42로 설정된
Example
클래스의 새 인스턴스에 메서드를 바인딩합니다. 즉, 대리자를 호출할 때마다Example
인스턴스가 메서드의 첫 번째 매개 변수에 전달됩니다.메서드의 첫 번째 매개 변수는 항상
Example
인스턴스를 받기 때문에OneParameter
대리자가 사용됩니다. 대리자를 호출하는 경우 두 번째 매개 변수만 필요합니다.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))
예시
다음 코드 예제에서는 간단한 동적 메서드 및 클래스 인스턴스에 바인딩된 동적 메서드를 보여 줍니다.
간단한 동적 메서드는 32비트 정수인 인수 하나를 사용하고 해당 정수의 64비트 거듭제곱을 반환합니다. 제네릭 대리자는 메서드를 호출하는 데 사용됩니다.
두 번째 동적 메서드에는 Example
형식과 int
(Visual Basic에서는 Integer
) 형식의 두 매개 변수가 있습니다. 동적 메서드를 만들면 int
형식의 인수 하나가 있는 제네릭 대리자를 사용하여 Example
인스턴스에 바인딩됩니다. 메서드의 첫 번째 매개 변수는 항상 Example
의 바인딩된 인스턴스를 받기 때문에 대리자에 Example
형식의 인수가 없습니다. 대리자를 호출할 때 int
인수만 제공됩니다. 이 동적 메서드는 Example
클래스의 private 필드에 액세스하고 private 필드와 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 = {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
'
참고 항목
.NET