Vorgehensweise: Definieren und Ausführen von dynamischen Methoden
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. Weitere Informationen zu dynamischen Methoden finden Sie in der DynamicMethod-Klasse.
Deklarieren Sie einen Delegattyp, um die Methode auszuführen. Erwägen Sie, einen generischen Delegaten zu verwenden, um die Anzahl der Delegattypen zu minimieren, die Sie benötigen. Der folgende Code deklariert zwei Delegattypen, die für eine
SquareIt
-Methode verwendet werden könnt. Eine Methode davon ist generisch.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
Erstellen Sie ein Array, das die Parametertypen für die dynamische Methode angibt. In diesem Beispiel ist der einzige Parameter ein
int
(Integer
in Visual Basic), also verfügt das Array nur über ein Element.array<Type^>^ methodArgs = { int::typeid };
Type[] methodArgs = {typeof(int)};
Dim methodArgs As Type() = {GetType(Integer)}
Erstellen Sie eine DynamicMethod. In diesem Beispiel trägt die Methode die Bezeichnung
SquareIt
.Hinweis
Es ist nicht nötig, den dynamischen Methoden Namen zu geben. Sie können auch nicht nach Namen aufgerufen werden. Mehrere dynamische Methoden können über denselben Namen verfügen. Jedoch erscheint der Name in Aufruflisten und kann für das Debuggen hilfreich sein.
Der Typ des Rückgabewerts ist als
long
angegeben. Die Methode ist dem Modul zugeordnet, das dieExample
-Klasse besitzt, die den Beispielcode enthält. Jedes geladene Modul kann angegeben werden. Die dynamische Methode verhält sich wie einestatic
-Methode auf Modulebene (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)
Geben Sie den Methodentext aus. In diesem Beispiel wird ein ILGenerator-Objekt zum Ausgeben der Common Intermediate Language (CIL) verwendet. Alternativ kann ein DynamicILInfo-Objekt in Kombination mit nicht verwalteten Codegeneratoren verwendet werden, um den Methodentext für eine DynamicMethod auszugeben.
Der CIL-Code lädt in diesem Beispiel das Argument (ein
int
) in den Stapel, konvertiert es zulong
, dupliziertlong
und multipliziert die beiden Zahlen. Dadurch verbleibt das quadratische Ergebnis im Stapel, und die Methode muss lediglich wieder zurückspringen.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)
Erstellen Sie eine Instanz des Delegaten (in Schritt 1 deklariert), der die dynamische Methode durch Aufruf der CreateDelegate-Methode darstellt. Durch die Erstellung des Delegaten wird die Methode abgeschlossen und alle weiteren Versuche, die Methode zu ändern, z. B. durch Hinzufügen von zusätzlichem CIL-Code, werden ignoriert. Der folgende Code erstellt den Delegaten und ruft ihn mithilfe eines generischen Delegaten auf.
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))
Deklarieren Sie einen Delegattyp, um die Methode auszuführen. Erwägen Sie, einen generischen Delegaten zu verwenden, um die Anzahl der Delegattypen zu minimieren, die Sie benötigen. 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.
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
Erstellen Sie ein Array, das die Parametertypen für die dynamische Methode angibt. 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. In diesem Beispiel gibt es zwei Parameter vom Typ
Example
undint
(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)}
Erstellen Sie eine DynamicMethod. In diesem Beispiel hat die Methode keinen Namen. Der Typ des Rückgabewerts ist als
int
(Integer
in Visual Basic) angegeben. Die Methode hat Zugriff auf die privaten und geschützten Member derExample
-Klasse.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))
Geben Sie den Methodentext aus. In diesem Beispiel wird ein ILGenerator-Objekt zum Ausgeben der Common Intermediate Language (CIL) verwendet. Alternativ kann ein DynamicILInfo-Objekt in Kombination mit nicht verwalteten Codegeneratoren verwendet werden, um den Methodentext für eine DynamicMethod auszugeben.
Der CIL-Code lädt in diesem Beispiel das erste Argument, das eine Instanz der
Example
-Klasse ist, und verwendet es, um den Wert eines privaten Instanzenfelds vom Typint
zu laden. Das zweite Argument wird geladen, und zwei Zahlen werden multipliziert. Wenn das Ergebnis größer alsint
ist, wird der Wert abgeschnitten und die wichtigsten Teile verworfen. Die Methode springt zurück und der zurückzugebende Wert befindet sich auf dem Stapel.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)
Erstellen Sie eine Instanz des Delegaten (in Schritt 1 deklariert), der die dynamische Methode durch Aufruf der CreateDelegate(Type, Object)-Methodenüberladung darstellt. Durch die Erstellung des Delegaten wird die Methode abgeschlossen und alle weiteren Versuche, die Methode zu ändern, z. B. durch Hinzufügen von weiterem CIL-Code, werden ignoriert.
Hinweis
Sie können die CreateDelegate-Methode mehrfach aufrufen, um die Delegaten zu erstellen, die an andere Instanzen des Zieltyps gebunden sind.
Der folgende Code bindet die Methode an eine neue Instanz der
Example
-Klasse, deren privates Testfeld auf 42 festgelegt ist. Das heißt, dass jedes Mal, wenn der Delegat aufgerufen wird, die Instanz vonExample
an den ersten Parameter der Methode übergeben wird.Der Delegat
OneParameter
wird verwendet, da der erste Parameter der Methode immer die Instanz vonExample
erhält. Wenn der Delegat aufgerufen wird, ist nur der zweite Parameter erforderlich.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))
Beispiel
Das folgende Codebeispiel zeigt eine einfache dynamische Methode sowie eine dynamische Methode, die an eine Instanz einer Klasse gebunden ist.
Die einfache dynamische Methode nimmt ein Argument, einen 32-Bit-Integer und gibt das 64-Bit-Quadrat dieses Integers zurück. Ein generischer Delegat wird zum Aufrufen der Methode verwendet.
Die zweite dynamische Methode hat zwei Parameter des Typs Example
und 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. Der Delegat besitzt kein Argument vom Typ Example
, da der erste Parameter der Methode immer die gebundene Instanz von Example
erhält. Wenn der Delegat aufgerufen wird, wird nur das int
-Argument bereitgestellt. 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.
Das Codebeispiel definiert Delegaten, die zum Ausführen dieser Methoden verwendet werden können.
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
'