DynamicMethod.CreateDelegate Metoda
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Dokončí dynamickou metodu a vytvoří delegáta, který lze použít k jejímu spuštění.
Přetížení
CreateDelegate(Type) |
Dokončí dynamickou metodu a vytvoří delegáta, který lze použít k jejímu spuštění. |
CreateDelegate(Type, Object) |
Dokončí dynamickou metodu a vytvoří delegáta, který lze použít k jejímu spuštění, a určí typ delegáta a objekt, ke kterému je delegát vázán. |
CreateDelegate(Type)
- Zdroj:
- DynamicMethod.cs
- Zdroj:
- DynamicMethod.CoreCLR.cs
- Zdroj:
- DynamicMethod.CoreCLR.cs
Dokončí dynamickou metodu a vytvoří delegáta, který lze použít k jejímu spuštění.
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
Parametry
- delegateType
- Type
Typ delegáta, jehož podpis odpovídá podpisu dynamické metody.
Návraty
Delegát zadaného typu, který lze použít ke spuštění dynamické metody.
- Atributy
Výjimky
Dynamická metoda nemá žádné tělo metody.
delegateType
má nesprávný počet parametrů nebo nesprávné typy parametrů.
Příklady
Následující příklad kódu vytvoří dynamickou metodu, která přijímá dva parametry. Příklad vygeneruje jednoduché tělo funkce, která vypíše první parametr do konzoly, a tento příklad používá druhý parametr jako návratovou hodnotu metody. Příklad dokončí metodu vytvořením delegáta, vyvolá delegáta s různými parametry a nakonec vyvolá dynamickou metodu Invoke pomocí metody .
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
'
Poznámky
Volání metody CreateDelegate nebo Invoke metody dokončí dynamickou metodu. Jakékoli další pokusy o změnu dynamické metody, jako je například úprava definic parametrů nebo generování více zprostředkující jazyk (MSIL) Společnosti Microsoft, jsou ignorovány; nevyvolá se žádná výjimka.
Chcete-li vytvořit tělo metody pro dynamickou metodu, pokud máte vlastní generátor jazyka MSIL, zavolejte metodu GetDynamicILInfo pro získání objektu DynamicILInfo . Pokud nemáte vlastní generátor jazyka MSIL, voláním GetILGenerator metody získejte ILGenerator objekt, který lze použít k vygenerování těla metody.
Viz také
Platí pro
CreateDelegate(Type, Object)
- Zdroj:
- DynamicMethod.cs
- Zdroj:
- DynamicMethod.CoreCLR.cs
- Zdroj:
- DynamicMethod.CoreCLR.cs
Dokončí dynamickou metodu a vytvoří delegáta, který lze použít k jejímu spuštění, a určí typ delegáta a objekt, ke kterému je delegát vázán.
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
Parametry
- delegateType
- Type
Typ delegáta, jehož podpis odpovídá podpisu dynamické metody minus první parametr.
- target
- Object
Objekt, ke který je delegát vázán. Musí být stejného typu jako první parametr dynamické metody.
Návraty
Delegát zadaného typu, který lze použít ke spuštění dynamické metody se zadaným cílovým objektem.
- Atributy
Výjimky
Dynamická metoda nemá žádné tělo metody.
target
není stejný typ jako první parametr dynamické metody a nelze ho k ho přiřadit.
-nebo-
delegateType
má nesprávný počet parametrů nebo nesprávné typy parametrů.
Příklady
Následující příklad kódu vytvoří delegáta, který vytvoří vazbu DynamicMethod s instancí typu, takže metoda funguje na stejné instanci pokaždé, když je vyvolána.
Příklad kódu definuje třídu s názvem Example
private pole, třídu s názvem DerivedFromExample
, která je odvozena z první třídy, typu delegáta s názvem UseLikeStatic
, který vrací Int32 a má parametry typu Example
a Int32a a typu delegáta s názvem UseLikeInstance
, který vrací Int32 a má jeden parametr typu Int32.
Ukázkový kód pak vytvoří , DynamicMethod který změní privátní pole instance Example
a vrátí předchozí hodnotu.
Poznámka
Obecně platí, že změna interních polí tříd není dobrá praxe kódování orientované na objekty.
Ukázkový kód vytvoří instanci Example
a pak vytvoří dva delegáty. První je typu UseLikeStatic
, který má stejné parametry jako dynamická metoda. Druhá je typu UseLikeInstance
, kterému chybí první parametr (typu Example
). Tento delegát se vytvoří pomocí CreateDelegate(Type, Object) přetížení metody; druhým parametrem přetížení metody je instance Example
, v tomto případě právě vytvořená instance, která je svázaná s nově vytvořeným delegátem. Při každém vyvolání tohoto delegáta dynamická metoda působí na vázané instanci objektu Example
.
Poznámka
Toto je příklad uvolněných pravidel pro vazbu delegáta zavedených v rozhraní .NET Framework 2.0 spolu s novými přetíženími Delegate.CreateDelegate metody . Další informace najdete ve Delegate třídě .
Delegát UseLikeStatic
je vyvolán a předává instanci, Example
která je vázána na delegáta UseLikeInstance
. Potom je UseLikeInstance
vyvolán delegát tak, aby oba delegáti jednali na stejné instanci .Example
Změny v hodnotách interního pole se zobrazí po každém volání.
UseLikeInstance
Nakonec je delegát vázán na instanci DerivedFromExample
a volání delegáta se opakují.
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'
Poznámky
Toto přetížení metody vytvoří delegáta vázaného na konkrétní objekt. Takový delegát je údajně uzavřen kvůli prvnímu argumentu. I když je metoda statická, chová se, jako by to byla metoda instance; instance je target
.
Toto přetížení metody musí target
být stejného typu jako první parametr dynamické metody nebo musí být přiřaditelné k tomuto typu (například odvozené třídě). Podpis objektu delegateType
má všechny parametry dynamické metody s výjimkou první. Pokud má například dynamická metoda parametry , a , pak delegateType
má parametry Int32 a Byteje target
typu String.ByteInt32String
Volání metody CreateDelegate nebo Invoke metody dokončí dynamickou metodu. Jakékoli další pokusy o změnu dynamické metody, jako je například úprava definic parametrů nebo generování více zprostředkující jazyk (MSIL) Společnosti Microsoft, jsou ignorovány; nevyvolá se žádná výjimka.
Chcete-li vytvořit tělo metody pro dynamickou metodu, pokud máte vlastní generátor jazyka MSIL, zavolejte metodu GetDynamicILInfo pro získání objektu DynamicILInfo . Pokud nemáte vlastní generátor jazyka MSIL, voláním GetILGenerator metody získejte ILGenerator objekt, který lze použít k vygenerování těla metody.