DynamicMethod.CreateDelegate 方法

定義

完成動態方法並建立一個代理來執行。

多載

名稱 Description
CreateDelegate(Type)

完成動態方法並建立一個代理來執行。

CreateDelegate(Type, Object)

完成動態方法並建立一個代理,可用於執行,指定代理類型及代理綁定的物件。

CreateDelegate(Type)

完成動態方法並建立一個代理來執行。

public:
 Delegate ^ CreateDelegate(Type ^ delegateType);
public:
 override 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);
public override sealed Delegate CreateDelegate(Type delegateType);
[<System.Runtime.InteropServices.ComVisible(true)>]
member this.CreateDelegate : Type -> Delegate
[<System.Runtime.InteropServices.ComVisible(true)>]
override this.CreateDelegate : Type -> Delegate
override this.CreateDelegate : Type -> Delegate
Public Function CreateDelegate (delegateType As Type) As Delegate
Public Overrides NotOverridable Function CreateDelegate (delegateType As Type) As Delegate

參數

delegateType
Type

一個代理型態,其簽名與動態方法相符。

傳回

指定類型的代理,可用於執行動態方法。

屬性

例外狀況

動態方法沒有方法體。

delegateType 參數數量錯誤或參數類型錯誤。

範例

以下程式碼範例建立了一個動態方法,取兩個參數。 範例中會輸出一個簡單的函式主體,將第一個參數印入主控台,並使用第二個參數作為方法的回傳值。 範例完成方法的步驟是首先創建一個委託,然後以不同的參數調用該委託,最後使用Invoke方法調用動態方法。

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)

完成動態方法並建立一個代理,可用於執行,指定代理類型及代理綁定的物件。

public:
 Delegate ^ CreateDelegate(Type ^ delegateType, System::Object ^ target);
public:
 override Delegate ^ CreateDelegate(Type ^ delegateType, System::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);
public override sealed Delegate CreateDelegate(Type delegateType, object target);
[<System.Runtime.InteropServices.ComVisible(true)>]
member this.CreateDelegate : Type * obj -> Delegate
[<System.Runtime.InteropServices.ComVisible(true)>]
override this.CreateDelegate : Type * obj -> Delegate
override this.CreateDelegate : Type * obj -> Delegate
Public Function CreateDelegate (delegateType As Type, target As Object) As Delegate
Public Overrides NotOverridable Function CreateDelegate (delegateType As Type, target As Object) As Delegate

參數

delegateType
Type

一個代理型別,其簽名與動態方法相同,但去掉第一個參數。

target
Object

代表必須綁定的物件。 必須與動態方法的第一個參數類型相同。

傳回

指定類型的代理,可用於執行動態方法,並指定目標物件。

屬性

例外狀況

動態方法沒有方法體。

target 與動態方法的第一個參數不同,且無法指派到該類型。

-或-

delegateType 參數數量錯誤或參數類型錯誤。

範例

以下程式碼範例建立代理,將 a DynamicMethod 綁定到某型別的實例,使該方法每次被呼叫時都對同一實例進行動作。

程式碼範例定義了一個帶有私有欄位的類別Example,一個從第一個類別衍生出來的類別DerivedFromExample,一個名為UseLikeStatic的代理型別(返回Int32,且參數類型為ExampleInt32),以及一個名為UseLikeInstance的代理型別,返回Int32且有一個參數類型為Int32

範例程式碼接著建立DynamicMethod,改變Example實例的私有欄位並回傳先前的值。

Note

一般而言,改變類別的內部欄位並不是良好的物件導向編碼實務。

範例程式碼先建立一個 的 Example 實例,然後再建立兩個代理。 第一個是型別 UseLikeStatic,其參數與動態方法的相同。 第二種是型別 UseLikeInstance,但缺少第一個參數(型別 Example)。 這個代理是透過 CreateDelegate(Type, Object) 方法超載建立的;該方法超載的第二個參數是 的 Example一個實例,在此例中是剛建立的實例,該實例綁定於新建立的代理。 每當該代理被調用時,動態方法就會作用於綁定的 實例 Example

Note

這是 .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 簽名包含動態方法中除第一個參數外的所有參數。 例如,若動態方法有參數 StringInt32Byte,則 delegateType 有參數 Int32Byte; target 型別 String為 。

呼叫 該 CreateDelegate 方法或該 Invoke 方法即可完成動態方法。 任何進一步改變動態方法的嘗試,例如修改參數定義或輸出更多 Microsoft 中間語言(MSIL),都被忽略;沒有例外。

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

適用於