DynamicMethod.CreateDelegate 方法

定義

完成動態方法並建立可以用來執行它的委派。

多載

CreateDelegate(Type)

完成動態方法並建立可以用來執行它的委派。

CreateDelegate(Type, Object)

完成動態方法並建立可以用來執行它的委派,同時指定委派類型和委派繫結至的物件。

CreateDelegate(Type)

來源:
DynamicMethod.cs
來源:
DynamicMethod.CoreCLR.cs
來源:
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)

來源:
DynamicMethod.cs
來源:
DynamicMethod.CoreCLR.cs
來源:
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使用私用字段、衍生自第一個類別的類別、名為 UseLikeStaticDerivedFromExample 的委派型別、傳回Int32且具有 型ExampleInt32別參數的委派型別,以及名為 UseLikeInstanceInt32 的委派型別,且具有型別的Int32一個參數。

然後,範例程式代碼會建立 , DynamicMethod 以變更 實例 Example 的私人字段,並傳回先前的值。

注意

一般而言,變更類別的內部字段不是良好的面向物件程式代碼撰寫做法。

範例程式代碼會建立的 Example 實例,然後建立兩個委派。 第一個是 類型 UseLikeStatic,其參數與動態方法相同。 第二個類型為 ,其中缺少類型 UseLikeInstanceExample) 的第一個參數 (。 此委派是使用 CreateDelegate(Type, Object) 方法多載所建立;該方法多載的第二個參數是 的 Example實例,在此情況下,剛建立的實例會系結至新建立的委派。 每當叫用該委派時,動態方法就會作用於 的 Example系結實例。

注意

這是 .NET Framework 2.0 中引進的委派系結寬鬆規則範例,以及方法的新多載Delegate.CreateDelegate。 如需詳細資訊,請參閱 Delegate 類別。

UseLikeStatic用委派,傳入系結至委派的 UseLikeInstance 實例Example。 接著會 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,且 Bytetarget 類型為 StringByteInt32String

CreateDelegate呼叫 方法或 Invoke 方法會完成動態方法。 會忽略任何進一步嘗試改變動態方法,例如修改參數定義或發出更多 Microsoft 中繼語言 (MSIL) ;不會擲回例外狀況。

若要在擁有自己的 MSIL 產生器時建立動態方法的方法主體,請呼叫 GetDynamicILInfo 方法來取得 DynamicILInfo 物件。 如果您沒有自己的 MSIL 產生器,請呼叫 GetILGenerator 方法以取得 ILGenerator 可用來產生方法主體的物件。

適用於