如何:定義和執行動態方法
下列程序顯示如何定義及執行簡單的動態方法及繫結至類別執行個體的動態方法。 如需動態方法的詳細資訊,請參閱 類別 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 物件結合 Unmanaged 程式碼產生器,發出 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
類別的私用和受保護成員。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 物件結合 Unmanaged 程式碼產生器,發出 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 方法,建立繫結至其他目標類型執行個體的委派。
下列程式碼會將方法繫結至
Example
類別的新執行個體,此類別的私用測試欄位設為 42。 亦即,每次叫用委派時,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
類別的私用欄位,並傳回私用欄位和 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
'