DynamicMethod.CreateDelegate 方法
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
完成动态方法并创建一个可执行此方法的委托。
重载
CreateDelegate(Type) |
完成动态方法并创建一个可执行此方法的委托。 |
CreateDelegate(Type, Object) |
完成动态方法并创建一个可用于执行该方法的委托,指定委托类型和委托绑定到的对象。 |
CreateDelegate(Type)
- Source:
- DynamicMethod.cs
- Source:
- DynamicMethod.CoreCLR.cs
- Source:
- DynamicMethod.CoreCLR.cs
完成动态方法并创建一个可执行此方法的委托。
public:
override Delegate ^ CreateDelegate(Type ^ delegateType);
public:
Delegate ^ CreateDelegate(Type ^ delegateType);
public override sealed Delegate CreateDelegate (Type delegateType);
[System.Runtime.InteropServices.ComVisible(true)]
public Delegate CreateDelegate (Type delegateType);
[System.Runtime.InteropServices.ComVisible(true)]
public override sealed Delegate CreateDelegate (Type delegateType);
override this.CreateDelegate : Type -> Delegate
[<System.Runtime.InteropServices.ComVisible(true)>]
member this.CreateDelegate : Type -> Delegate
[<System.Runtime.InteropServices.ComVisible(true)>]
override this.CreateDelegate : Type -> Delegate
Public Overrides NotOverridable Function CreateDelegate (delegateType As Type) As Delegate
Public Function CreateDelegate (delegateType As Type) As Delegate
参数
- delegateType
- Type
其签名与动态方法匹配的委托类型。
返回
可用于执行此动态方法的指定类型的委托。
- 属性
例外
动态方法没有方法体。
delegateType
的参数数量或参数类型不正确。
示例
下面的代码示例创建一个采用两个参数的动态方法。 该示例发出一个简单的函数体,该函数体将第一个参数打印到控制台,该示例使用第二个参数作为 方法的返回值。 该示例通过创建委托完成方法,使用不同参数调用委托,最后使用 Invoke 方法调用动态方法。
using namespace System;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
public ref class Test
{
};
// Declare a delegate that will be used to execute the completed
// dynamic method.
delegate int HelloInvoker(String^ msg, int ret);
int main()
{
// Create an array that specifies the types of the parameters
// of the dynamic method. This method has a string parameter
// and an int parameter.
array<Type^>^ helloArgs = {String::typeid, int::typeid};
// Create a dynamic method with the name "Hello", a return type
// of int, and two parameters whose types are specified by the
// array helloArgs. Create the method in the module that
// defines the Test class.
DynamicMethod^ hello = gcnew DynamicMethod("Hello",
int::typeid,
helloArgs,
Test::typeid->Module);
// Create an array that specifies the parameter types of the
// overload of Console.WriteLine to be used in Hello.
array<Type^>^ writeStringArgs = {String::typeid};
// Get the overload of Console.WriteLine that has one
// String parameter.
MethodInfo^ writeString =
Console::typeid->GetMethod("WriteLine", writeStringArgs);
// Get an ILGenerator and emit a body for the dynamic method.
ILGenerator^ ilgen = hello->GetILGenerator();
// Load the first argument, which is a string, onto the stack.
ilgen->Emit(OpCodes::Ldarg_0);
// Call the overload of Console.WriteLine that prints a string.
ilgen->EmitCall(OpCodes::Call, writeString, nullptr);
// The Hello method returns the value of the second argument;
// to do this, load the onto the stack and return.
ilgen->Emit(OpCodes::Ldarg_1);
ilgen->Emit(OpCodes::Ret);
// Create a delegate that represents the dynamic method. This
// action completes the method, and any further attempts to
// change the method will cause an exception.
HelloInvoker^ helloDelegate =
(HelloInvoker^) hello->CreateDelegate(HelloInvoker::typeid);
// Use the delegate to execute the dynamic method. Save and
// print the return value.
int returnValue = helloDelegate("\r\nHello, World!", 42);
Console::WriteLine("helloDelegate(\"Hello, World!\", 42) returned {0}",
returnValue);
// Do it again, with different arguments.
returnValue = helloDelegate("\r\nHi, Mom!", 5280);
Console::WriteLine("helloDelegate(\"Hi, Mom!\", 5280) returned {0}",
returnValue);
// Create an array of arguments to use with the Invoke method.
array<Object^>^ delegateArgs = {"\r\nHello, World!", 42};
// Invoke the dynamic method using the arguments. This is much
// slower than using the delegate, because you must create an
// array to contain the arguments, and ValueType arguments
// must be boxed.
Object^ returnValueObject = hello->Invoke(nullptr, delegateArgs);
Console::WriteLine("hello.Invoke returned {0}", returnValueObject);
}
using System;
using System.Reflection;
using System.Reflection.Emit;
using Microsoft.VisualBasic;
public class Test
{
// Declare a delegate that will be used to execute the completed
// dynamic method.
private delegate int HelloInvoker(string msg, int ret);
public static void Main()
{
// Create an array that specifies the types of the parameters
// of the dynamic method. This method has a string parameter
// and an int parameter.
Type[] helloArgs = {typeof(string), typeof(int)};
// Create a dynamic method with the name "Hello", a return type
// of int, and two parameters whose types are specified by the
// array helloArgs. Create the method in the module that
// defines the Test class.
DynamicMethod hello = new DynamicMethod("Hello",
typeof(int),
helloArgs,
typeof(Test).Module);
// Create an array that specifies the parameter types of the
// overload of Console.WriteLine to be used in Hello.
Type[] writeStringArgs = {typeof(string)};
// Get the overload of Console.WriteLine that has one
// String parameter.
MethodInfo writeString =
typeof(Console).GetMethod("WriteLine", writeStringArgs);
// Get an ILGenerator and emit a body for the dynamic method.
ILGenerator il = hello.GetILGenerator();
// Load the first argument, which is a string, onto the stack.
il.Emit(OpCodes.Ldarg_0);
// Call the overload of Console.WriteLine that prints a string.
il.EmitCall(OpCodes.Call, writeString, null);
// The Hello method returns the value of the second argument;
// to do this, load the onto the stack and return.
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method. This
// action completes the method, and any further attempts to
// change the method will cause an exception.
HelloInvoker hi =
(HelloInvoker) hello.CreateDelegate(typeof(HelloInvoker));
// Use the delegate to execute the dynamic method. Save and
// print the return value.
int retval = hi("\r\nHello, World!", 42);
Console.WriteLine("Executing delegate hi(\"Hello, World!\", 42) returned {0}",
retval);
// Do it again, with different arguments.
retval = hi("\r\nHi, Mom!", 5280);
Console.WriteLine("Executing delegate hi(\"Hi, Mom!\", 5280) returned {0}",
retval);
// Create an array of arguments to use with the Invoke method.
object[] invokeArgs = {"\r\nHello, World!", 42};
// Invoke the dynamic method using the arguments. This is much
// slower than using the delegate, because you must create an
// array to contain the arguments, and ValueType arguments
// must be boxed.
object objRet = hello.Invoke(null, invokeArgs);
Console.WriteLine("hello.Invoke returned {0}", objRet);
}
}
Imports System.Reflection
Imports System.Reflection.Emit
Public Class Test
' Declare a delegate that will be used to execute the completed
' dynamic method.
Private Delegate Function HelloInvoker(ByVal msg As String, _
ByVal ret As Integer) As Integer
Public Shared Sub Main()
' Create an array that specifies the types of the parameters
' of the dynamic method. This method has a String parameter
' and an Integer parameter.
Dim helloArgs() As Type = {GetType(String), GetType(Integer)}
' Create a dynamic method with the name "Hello", a return type
' of Integer, and two parameters whose types are specified by
' the array helloArgs. Create the method in the module that
' defines the Test class.
Dim hello As New DynamicMethod("Hello", _
GetType(Integer), _
helloArgs, _
GetType(Test).Module)
' Create an array that specifies the parameter types of the
' overload of Console.WriteLine to be used in Hello.
Dim writeStringArgs() As Type = {GetType(String)}
' Get the overload of Console.WriteLine that has one
' String parameter.
Dim writeString As MethodInfo = GetType(Console). _
GetMethod("WriteLine", writeStringArgs)
' Get an ILGenerator and emit a body for the dynamic method.
Dim il As ILGenerator = hello.GetILGenerator()
' Load the first argument, which is a string, onto the stack.
il.Emit(OpCodes.Ldarg_0)
' Call the overload of Console.WriteLine that prints a string.
il.EmitCall(OpCodes.Call, writeString, Nothing)
' The Hello method returns the value of the second argument;
' to do this, load the onto the stack and return.
il.Emit(OpCodes.Ldarg_1)
il.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method. This
' action completes the method, and any further attempts to
' change the method will cause an exception.
Dim hi As HelloInvoker = _
hello.CreateDelegate(GetType(HelloInvoker))
' Use the delegate to execute the dynamic method. Save and
' print the return value.
Dim retval As Integer = hi(vbCrLf & "Hello, World!", 42)
Console.WriteLine("Executing delegate hi(""Hello, World!"", 42) returned " _
& retval)
' Do it again, with different arguments.
retval = hi(vbCrLf & "Hi, Mom!", 5280)
Console.WriteLine("Executing delegate hi(""Hi, Mom!"", 5280) returned " _
& retval)
' Create an array of arguments to use with the Invoke method.
Dim invokeArgs() As Object = {vbCrLf & "Hello, World!", 42}
' Invoke the dynamic method using the arguments. This is much
' slower than using the delegate, because you must create an
' array to contain the arguments, and ValueType arguments
' must be boxed. Note that this overload of Invoke is
' inherited from MethodBase, and simply calls the more
' complete overload of Invoke.
Dim objRet As Object = hello.Invoke(Nothing, invokeArgs)
Console.WriteLine("hello.Invoke returned " & objRet)
End Sub
End Class
' This code example produces the following output:
'
'Hello, World!
'Executing delegate hi("Hello, World!", 42) returned 42
'
'Hi, Mom!
'Executing delegate hi("Hi, Mom!", 5280) returned 5280
'
'Hello, World!
'hello.Invoke returned 42
'
注解
CreateDelegate调用 方法或 Invoke 方法完成动态方法。 将忽略任何进一步更改动态方法的尝试,例如修改参数定义或发出更多 Microsoft 中间语言 (MSIL) ;不会引发异常。
若要在具有自己的 MSIL 生成器时为动态方法创建方法主体,请调用 GetDynamicILInfo 方法来获取 DynamicILInfo 对象。 如果没有自己的 MSIL 生成器,请调用 GetILGenerator 方法以获取 ILGenerator 可用于生成方法正文的对象。
另请参阅
适用于
CreateDelegate(Type, Object)
- Source:
- DynamicMethod.cs
- Source:
- DynamicMethod.CoreCLR.cs
- Source:
- DynamicMethod.CoreCLR.cs
完成动态方法并创建一个可用于执行该方法的委托,指定委托类型和委托绑定到的对象。
public:
override Delegate ^ CreateDelegate(Type ^ delegateType, System::Object ^ target);
public:
Delegate ^ CreateDelegate(Type ^ delegateType, System::Object ^ target);
public override sealed Delegate CreateDelegate (Type delegateType, object? target);
public override sealed Delegate CreateDelegate (Type delegateType, object target);
[System.Runtime.InteropServices.ComVisible(true)]
public Delegate CreateDelegate (Type delegateType, object target);
[System.Runtime.InteropServices.ComVisible(true)]
public override sealed Delegate CreateDelegate (Type delegateType, object target);
override this.CreateDelegate : Type * obj -> Delegate
[<System.Runtime.InteropServices.ComVisible(true)>]
member this.CreateDelegate : Type * obj -> Delegate
[<System.Runtime.InteropServices.ComVisible(true)>]
override this.CreateDelegate : Type * obj -> Delegate
Public Overrides NotOverridable Function CreateDelegate (delegateType As Type, target As Object) As Delegate
Public Function CreateDelegate (delegateType As Type, target As Object) As Delegate
参数
- delegateType
- Type
一个签名与动态方法的签名匹配的委托类型,不包括第一个参数。
- target
- Object
委托绑定到的对象。 其类型必须与动态方法的第一个参数的类型相同。
返回
一个指定类型的委托,可用于对指定的目标对象执行动态方法。
- 属性
例外
动态方法没有方法体。
示例
下面的代码示例创建委托,该委托将 绑定到 DynamicMethod 类型的实例,以便每次调用该方法时都对同一实例执行操作。
代码示例定义了一个名为 的类 Example
,其中包含一个私有字段,一个名为 的 DerivedFromExample
类派生自第一个类,一个名为 UseLikeStatic
的委托类型,该委托类型返回 Int32 并具有 类型 Example
为 和 Int32的参数,以及一个名为 的委托类型,该委托类型 UseLikeInstance
返回 Int32 并具有一个 类型 Int32参数。
然后,示例代码创建一个 , DynamicMethod 用于更改 实例 Example
的私有字段并返回以前的值。
注意
通常,更改类的内部字段不是面向对象的良好编码做法。
示例代码创建 的 Example
实例,然后创建两个委托。 第一个 UseLikeStatic
类型为 ,其参数与动态方法相同。 第二个类型 UseLikeInstance
为 ,缺少类型) Example
的第一个参数 (。 此委托是使用 CreateDelegate(Type, Object) 方法重载创建的;该方法重载的第二个参数是 的 Example
实例,在本例中是刚刚创建的实例,该实例绑定到新创建的委托。 每当调用该委托时,动态方法就会作用于 的 Example
绑定实例。
注意
这是 .NET Framework 2.0 中引入的委托绑定的宽松规则以及 方法的新重载的示例Delegate.CreateDelegate。 有关更多信息,请参见 Delegate 类。
调用 UseLikeStatic
委托,传入绑定到委托的 Example
UseLikeInstance
实例。 然后调用委托 UseLikeInstance
,以便两个委托对 的 Example
同一实例执行操作。 每次调用后,都会显示内部字段的值更改。 最后,委托 UseLikeInstance
绑定到 的 DerivedFromExample
实例,并重复委托调用。
using System;
using System.Reflection;
using System.Reflection.Emit;
// These classes are for demonstration purposes.
//
public class Example
{
private int id = 0;
public Example(int id)
{
this.id = id;
}
public int ID { get { return id; }}
}
public class DerivedFromExample : Example
{
public DerivedFromExample(int id) : base(id) {}
}
// Two delegates are declared: UseLikeInstance treats the dynamic
// method as if it were an instance method, and UseLikeStatic
// treats the dynamic method in the ordinary fashion.
//
public delegate int UseLikeInstance(int newID);
public delegate int UseLikeStatic(Example ex, int newID);
public class Demo
{
public static void Main()
{
// This dynamic method changes the private id field. It has
// no name; it returns the old id value (return type int);
// it takes two parameters, an instance of Example and
// an int that is the new value of id; and it is declared
// with Example as the owner type, so it can access all
// members, public and private.
//
DynamicMethod changeID = new DynamicMethod(
"",
typeof(int),
new Type[] { typeof(Example), typeof(int) },
typeof(Example)
);
// Get a FieldInfo for the private field 'id'.
FieldInfo fid = typeof(Example).GetField(
"id",
BindingFlags.NonPublic | BindingFlags.Instance
);
ILGenerator ilg = changeID.GetILGenerator();
// Push the current value of the id field onto the
// evaluation stack. It's an instance field, so load the
// instance of Example before accessing the field.
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldfld, fid);
// Load the instance of Example again, load the new value
// of id, and store the new field value.
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldarg_1);
ilg.Emit(OpCodes.Stfld, fid);
// The original value of the id field is now the only
// thing on the stack, so return from the call.
ilg.Emit(OpCodes.Ret);
// Create a delegate that uses changeID in the ordinary
// way, as a static method that takes an instance of
// Example and an int.
//
UseLikeStatic uls =
(UseLikeStatic) changeID.CreateDelegate(
typeof(UseLikeStatic)
);
// Create an instance of Example with an id of 42.
//
Example ex = new Example(42);
// Create a delegate that is bound to the instance of
// of Example. This is possible because the first
// parameter of changeID is of type Example. The
// delegate has all the parameters of changeID except
// the first.
UseLikeInstance uli =
(UseLikeInstance) changeID.CreateDelegate(
typeof(UseLikeInstance),
ex
);
// First, change the value of id by calling changeID as
// a static method, passing in the instance of Example.
//
Console.WriteLine(
"Change the value of id; previous value: {0}",
uls(ex, 1492)
);
// Change the value of id again using the delegate bound
// to the instance of Example.
//
Console.WriteLine(
"Change the value of id; previous value: {0}",
uli(2700)
);
Console.WriteLine("Final value of id: {0}", ex.ID);
// Now repeat the process with a class that derives
// from Example.
//
DerivedFromExample dfex = new DerivedFromExample(71);
uli = (UseLikeInstance) changeID.CreateDelegate(
typeof(UseLikeInstance),
dfex
);
Console.WriteLine(
"Change the value of id; previous value: {0}",
uls(dfex, 73)
);
Console.WriteLine(
"Change the value of id; previous value: {0}",
uli(79)
);
Console.WriteLine("Final value of id: {0}", dfex.ID);
}
}
/* This code example produces the following output:
Change the value of id; previous value: 42
Change the value of id; previous value: 1492
Final value of id: 2700
Change the value of id; previous value: 71
Change the value of id; previous value: 73
Final value of id: 79
*/
Imports System.Reflection
Imports System.Reflection.Emit
' These classes are for demonstration purposes.
'
Public Class Example
Private _id As Integer = 0
Public Sub New(ByVal newId As Integer)
_id = newId
End Sub
Public ReadOnly Property ID() As Integer
Get
Return _id
End Get
End Property
End Class
Public Class DerivedFromExample
Inherits Example
Public Sub New(ByVal newId As Integer)
MyBase.New(newId)
End Sub
End Class
' Two delegates are declared: UseLikeInstance treats the dynamic
' method as if it were an instance method, and UseLikeStatic
' treats the dynamic method in the ordinary fashion.
'
Public Delegate Function UseLikeInstance(ByVal newID As Integer) _
As Integer
Public Delegate Function UseLikeStatic(ByVal ex As Example, _
ByVal newID As Integer) As Integer
Public Class Demo
Public Shared Sub Main()
' This dynamic method changes the private _id field. It
' has no name; it returns the old _id value (return type
' Integer); it takes two parameters, an instance of Example
' and an Integer that is the new value of _id; and it is
' declared with Example as the owner type, so it can
' access all members, public and private.
'
Dim changeID As New DynamicMethod( _
"", _
GetType(Integer), _
New Type() {GetType(Example), GetType(Integer)}, _
GetType(Example) _
)
' Get a FieldInfo for the private field '_id'.
Dim fid As FieldInfo = GetType(Example).GetField( _
"_id", _
BindingFlags.NonPublic Or BindingFlags.Instance _
)
Dim ilg As ILGenerator = changeID.GetILGenerator()
' Push the current value of the id field onto the
' evaluation stack. It's an instance field, so load the
' instance of Example before accessing the field.
ilg.Emit(OpCodes.Ldarg_0)
ilg.Emit(OpCodes.Ldfld, fid)
' Load the instance of Example again, load the new value
' of id, and store the new field value.
ilg.Emit(OpCodes.Ldarg_0)
ilg.Emit(OpCodes.Ldarg_1)
ilg.Emit(OpCodes.Stfld, fid)
' The original value of the id field is now the only
' thing on the stack, so return from the call.
ilg.Emit(OpCodes.Ret)
' Create a delegate that uses changeID in the ordinary
' way, as a static method that takes an instance of
' Example and an Integer.
'
Dim uls As UseLikeStatic = CType( _
changeID.CreateDelegate(GetType(UseLikeStatic)), _
UseLikeStatic _
)
' Create an instance of Example with an id of 42.
'
Dim ex As New Example(42)
' Create a delegate that is bound to the instance of
' of Example. This is possible because the first
' parameter of changeID is of type Example. The
' delegate has all the parameters of changeID except
' the first.
Dim uli As UseLikeInstance = CType( _
changeID.CreateDelegate( _
GetType(UseLikeInstance), _
ex), _
UseLikeInstance _
)
' First, change the value of _id by calling changeID as
' a static method, passing in the instance of Example.
'
Console.WriteLine( _
"Change the value of _id; previous value: {0}", _
uls(ex, 1492) _
)
' Change the value of _id again using the delegate
' bound to the instance of Example.
'
Console.WriteLine( _
"Change the value of _id; previous value: {0}", _
uli(2700) _
)
Console.WriteLine("Final value of _id: {0}", ex.ID)
' Now repeat the process with a class that derives
' from Example.
'
Dim dfex As New DerivedFromExample(71)
uli = CType( _
changeID.CreateDelegate( _
GetType(UseLikeInstance), _
dfex), _
UseLikeInstance _
)
Console.WriteLine( _
"Change the value of _id; previous value: {0}", _
uls(dfex, 73) _
)
Console.WriteLine( _
"Change the value of _id; previous value: {0}", _
uli(79) _
)
Console.WriteLine("Final value of _id: {0}", dfex.ID)
End Sub
End Class
' This code example produces the following output:
'
'Change the value of _id; previous value: 42
'Change the value of _id; previous value: 1492
'Final value of _id: 2700
'Change the value of _id; previous value: 71
'Change the value of _id; previous value: 73
'Final value of _id: 79'
注解
此方法重载创建绑定到特定对象的委托。 据说,这种代表在第一个论点上被关闭。 虽然 该方法是静态的,但它的作用就像它是一个实例方法;实例为 target
。
此方法重载需要 target
与动态方法的第一个参数属于同一类型,或者要分配给该类型 (例如派生类) 。 的 delegateType
签名具有动态方法的所有参数,但第一个参数除外。 例如,如果动态方法具有参数 、 和 ,则delegateType
具有 参数 Int32 和 Byte;target
的类型为 String。ByteInt32String
CreateDelegate调用 方法或 Invoke 方法完成动态方法。 将忽略任何进一步更改动态方法的尝试,例如修改参数定义或发出更多 Microsoft 中间语言 (MSIL) ;不会引发异常。
若要在具有自己的 MSIL 生成器时为动态方法创建方法主体,请调用 GetDynamicILInfo 方法来获取 DynamicILInfo 对象。 如果没有自己的 MSIL 生成器,请调用 GetILGenerator 方法以获取 ILGenerator 可用于生成方法正文的对象。