DynamicMethod.CreateDelegate 方法

定义

完成动态方法并创建一个可执行此方法的委托。

重载

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

委托绑定到的对象。 其类型必须与动态方法的第一个参数的类型相同。

返回

一个指定类型的委托,可用于对指定的目标对象执行动态方法。

属性

例外

动态方法没有方法体。

target 的类型与动态方法的第一个参数的类型不同,不能赋值给该类型。

- 或 -

delegateType 的参数数量或参数类型不正确。

示例

下面的代码示例创建委托,该委托将 绑定到 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 委托,传入绑定到委托的 ExampleUseLikeInstance 实例。 然后调用委托 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具有 参数 Int32Byte;target的类型为 StringByteInt32String

CreateDelegate调用 方法或 Invoke 方法完成动态方法。 将忽略任何进一步更改动态方法的尝试,例如修改参数定义或发出更多 Microsoft 中间语言 (MSIL) ;不会引发异常。

若要在具有自己的 MSIL 生成器时为动态方法创建方法主体,请调用 GetDynamicILInfo 方法来获取 DynamicILInfo 对象。 如果没有自己的 MSIL 生成器,请调用 GetILGenerator 方法以获取 ILGenerator 可用于生成方法正文的对象。

适用于