Postupy: Definování a spouštění dynamických metod
Následující postupy ukazují, jak definovat a spustit jednoduchou dynamickou metodu a dynamickou metodu vázanou na instanci třídy. Další informace o dynamických metodách naleznete ve DynamicMethod třídě.
Deklarujte typ delegáta pro spuštění metody. Zvažte použití obecného delegáta k minimalizaci počtu typů delegátů, které potřebujete deklarovat. Následující kód deklaruje dva typy delegátů, které lze použít pro metodu
SquareIt
, a jeden z nich je obecný.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
Vytvořte pole, které určuje typy parametrů pro dynamickou metodu. V tomto příkladu je jediným parametrem
int
(Integer
v jazyce Visual Basic), takže pole má pouze jeden prvek.array<Type^>^ methodArgs = { int::typeid };
Type[] methodArgs = {typeof(int)};
Dim methodArgs As Type() = {GetType(Integer)}
Vytvoření souboru DynamicMethod. V tomto příkladu je metoda pojmenována
SquareIt
.Poznámka:
Není nutné pojmenovat dynamické metody a nelze je vyvolat názvem. Stejný název může mít více dynamických metod. Název se však zobrazí v zásobníkech volání a může být užitečný pro ladění.
Typ návratové hodnoty je určen jako
long
. Metoda je přidružena k modulu, který obsahujeExample
třídu, která obsahuje ukázkový kód. Je možné zadat libovolný načtený modul. Dynamická metoda funguje jako metoda na úrovnistatic
modulu (Shared
v jazyce 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)
Vygenerujte tělo metody. V tomto příkladu se ILGenerator objekt používá k generování společného zprostředkujícího jazyka (CIL). Alternativně DynamicILInfo lze objekt použít ve spojení s nespravovanými generátory kódu k vygenerování těla metody pro DynamicMethod.
CIL v tomto příkladu načte argument, což je
int
, do zásobníku, převede jej nalong
, duplikuje a vynásobílong
dvě čísla. To ponechá na zásobníku čtvercový výsledek a všechny metody musí provést, je vrácena.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)
Vytvořte instanci delegáta (deklarovaného v kroku 1), která představuje dynamickou metodu voláním CreateDelegate metody. Vytvoření delegáta dokončí metodu a všechny další pokusy o změnu metody ( například přidání dalšího souboru CIL) se ignorují. Následující kód vytvoří delegáta a vyvolá ho pomocí obecného delegáta.
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))
Deklarujte typ delegáta pro spuštění metody. Zvažte použití obecného delegáta k minimalizaci počtu typů delegátů, které potřebujete deklarovat. Následující kód deklaruje obecný typ delegáta, který lze použít ke spuštění jakékoli metody s jedním parametrem a návratovou hodnotou, nebo metodu se dvěma parametry a návratovou hodnotou, pokud je delegát vázán na objekt.
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
Vytvořte pole, které určuje typy parametrů pro dynamickou metodu. Pokud je delegát představující metodu vázán na objekt, musí první parametr odpovídat typu, ke které je delegát vázán. V tomto příkladu existují dva parametry typu
Example
a typuint
(Integer
v jazyce Visual Basic).array<Type^>^ methodArgs2 = { Example::typeid, int::typeid };
Type[] methodArgs2 = { typeof(Example), typeof(int) };
Dim methodArgs2 As Type() = _ {GetType(Example), GetType(Integer)}
Vytvoření souboru DynamicMethod. V tomto příkladu metoda nemá žádný název. Typ návratové hodnoty je určen jako
int
(Integer
v jazyce Visual Basic). Metoda má přístup k soukromým a chráněným členůmExample
třídy.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))
Vygenerujte tělo metody. V tomto příkladu se ILGenerator objekt používá k generování společného zprostředkujícího jazyka (CIL). Alternativně DynamicILInfo lze objekt použít ve spojení s nespravovanými generátory kódu k vygenerování těla metody pro DynamicMethod.
CIL v tomto příkladu načte první argument, což je instance
Example
třídy, a používá ji k načtení hodnoty pole privátní instance typuint
. Druhý argument se načte a dvě čísla se vynásobí. Pokud je výsledek větší,int
hodnota se zkrátí a nejvýznamnější bity se zahodí. Metoda vrátí návratovou hodnotu v zásobníku.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)
Vytvořte instanci delegáta (deklarovaného v kroku 1), která představuje dynamickou metodu voláním CreateDelegate(Type, Object) přetížení metody. Vytvoření delegáta dokončí metodu a všechny další pokusy o změnu metody (například přidání dalšího souboru CIL) se ignorují.
Poznámka:
Metodu CreateDelegate můžete volat vícekrát a vytvořit delegáty vázané na jiné instance cílového typu.
Následující kód vytvoří vazbu metody na novou instanci
Example
třídy, jejíž privátní testovací pole je nastaveno na hodnotu 42. To znamená, že při každém vyvolání delegáta je instanceExample
předána prvnímu parametru metody.OneParameter
Delegát se používá, protože první parametr metody vždy obdrží instanciExample
. Při vyvolání delegáta se vyžaduje pouze druhý parametr.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))
Příklad
Následující příklad kódu ukazuje jednoduchou dynamickou metodu a dynamickou metodu vázanou na instanci třídy.
Jednoduchá dynamická metoda přebírá jeden argument, 32bitové celé číslo a vrátí 64bitové čtverce tohoto celého čísla. K vyvolání metody se používá obecný delegát.
Druhá dynamická metoda má dva parametry typu Example
a typu int
(Integer
v jazyce Visual Basic). Při vytvoření dynamické metody je vázána na instanci Example
, pomocí obecného delegáta, který má jeden argument typu int
. Delegát nemá argument typu Example
, protože první parametr metody vždy obdrží vázané instance Example
. Při vyvolání delegáta int
je zadán pouze argument. Tato dynamická metoda přistupuje k privátnímu poli Example
třídy a vrátí součin soukromého pole a argumentu int
.
Příklad kódu definuje delegáty, které lze použít ke spuštění metod.
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
'