DynamicMethod.CreateDelegate 方法
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
完成動態方法並建立一個代理來執行。
多載
| 名稱 | 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
代表必須綁定的物件。 必須與動態方法的第一個參數類型相同。
傳回
指定類型的代理,可用於執行動態方法,並指定目標物件。
- 屬性
例外狀況
動態方法沒有方法體。
範例
以下程式碼範例建立代理,將 a DynamicMethod 綁定到某型別的實例,使該方法每次被呼叫時都對同一實例進行動作。
程式碼範例定義了一個帶有私有欄位的類別Example,一個從第一個類別衍生出來的類別DerivedFromExample,一個名為UseLikeStatic的代理型別(返回Int32,且參數類型為Example和Int32),以及一個名為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 簽名包含動態方法中除第一個參數外的所有參數。 例如,若動態方法有參數 String、 Int32、 Byte,則 delegateType 有參數 Int32 和 Byte; target 型別 String為 。
呼叫 該 CreateDelegate 方法或該 Invoke 方法即可完成動態方法。 任何進一步改變動態方法的嘗試,例如修改參數定義或輸出更多 Microsoft 中間語言(MSIL),都被忽略;沒有例外。
當你擁有自己的 MSIL 產生器時,要為動態方法建立方法體,請呼叫該 GetDynamicILInfo 方法來取得物件 DynamicILInfo 。 如果你沒有自己的 MSIL 產生器,呼叫該 GetILGenerator 方法以取得 ILGenerator 可用來產生方法主體的物件。