Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les procédures suivantes montrent comment définir et exécuter une méthode dynamique simple et une méthode dynamique liée à une instance d’une classe. Pour plus d’informations sur les méthodes dynamiques, consultez la DynamicMethod classe.
Déclarez un type délégué pour exécuter la méthode. Envisagez d’utiliser un délégué générique pour réduire le nombre de types délégués que vous devez déclarer. Le code suivant déclare deux types délégués qui peuvent être utilisés pour la
SquareIt
méthode, et l’un d’eux est générique.private delegate long SquareItInvoker(int input); private delegate TReturn OneParameter<TReturn, TParameter0> (TParameter0 p0);
Private Delegate Function _ SquareItInvoker(ByVal input As Integer) As Long Private Delegate Function _ OneParameter(Of TReturn, TParameter0) _ (ByVal p0 As TParameter0) As TReturn
Créez un tableau qui spécifie les types de paramètres pour la méthode dynamique. Dans cet exemple, le seul paramètre est un
int
(Integer
en Visual Basic), de sorte que le tableau n’a qu’un seul élément.Type[] methodArgs = {typeof(int)};
Dim methodArgs As Type() = {GetType(Integer)}
Créer un DynamicMethod. Dans cet exemple, la méthode est nommée
SquareIt
.Remarque
Il n’est pas nécessaire de donner des noms de méthodes dynamiques et ils ne peuvent pas être appelés par nom. Plusieurs méthodes dynamiques peuvent avoir le même nom. Toutefois, le nom apparaît dans les piles d’appels et peut s'avérer utile pour le débogage.
Le type de la valeur de retour est spécifié en tant que
long
. La méthode est associée au module qui contient laExample
classe, qui contient l’exemple de code. Tout module chargé peut être spécifié. La méthode dynamique agit comme une méthode au niveaustatic
du module (Shared
en Visual Basic).DynamicMethod squareIt = new DynamicMethod( "SquareIt", typeof(long), methodArgs, typeof(Example).Module);
Dim squareIt As New DynamicMethod( _ "SquareIt", _ GetType(Long), _ methodArgs, _ GetType(Example).Module)
Émettez le corps de la méthode. Dans cet exemple, un ILGenerator objet est utilisé pour émettre le langage intermédiaire commun (CIL). Vous pouvez également utiliser un DynamicILInfo objet conjointement avec des générateurs de code non managés pour émettre le corps de la méthode pour un DynamicMethod.
Le CIL dans cet exemple charge l'argument, qui est un
int
, sur la pile, le convertit en unlong
, duplique lelong
, et multiplie ainsi les deux nombres. Cela laisse le résultat carré sur la pile, et tout ce que la méthode doit faire est de retourner.ILGenerator il = squareIt.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Conv_I8); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Ret);
Dim il As ILGenerator = squareIt.GetILGenerator() il.Emit(OpCodes.Ldarg_0) il.Emit(OpCodes.Conv_I8) il.Emit(OpCodes.Dup) il.Emit(OpCodes.Mul) il.Emit(OpCodes.Ret)
Créez une instance du délégué (déclaré à l’étape 1) qui représente la méthode dynamique en appelant la CreateDelegate méthode. La création du délégué termine la méthode, et toute autre tentative de modification de la méthode (par exemple, l’ajout d’un CIL supplémentaire) est ignorée. Le code suivant crée le délégué et l’appelle à l’aide d’un délégué générique.
OneParameter<long, int> invokeSquareIt = (OneParameter<long, int>) squareIt.CreateDelegate(typeof(OneParameter<long, int>)); Console.WriteLine($"123456789 squared = {invokeSquareIt(123456789)}");
Dim invokeSquareIt As OneParameter(Of Long, Integer) = _ CType( _ squareIt.CreateDelegate( _ GetType(OneParameter(Of Long, Integer))), _ OneParameter(Of Long, Integer) _ ) Console.WriteLine("123456789 squared = {0}", _ invokeSquareIt(123456789))
Déclarez un type délégué pour exécuter la méthode. Envisagez d’utiliser un délégué générique pour réduire le nombre de types délégués que vous devez déclarer. Le code suivant déclare un type délégué générique qui peut être utilisé pour exécuter n’importe quelle méthode avec un paramètre et une valeur de retour, ou une méthode avec deux paramètres et une valeur de retour si le délégué est lié à un objet.
private delegate TReturn OneParameter<TReturn, TParameter0> (TParameter0 p0);
Private Delegate Function _ OneParameter(Of TReturn, TParameter0) _ (ByVal p0 As TParameter0) As TReturn
Créez un tableau qui spécifie les types de paramètres pour la méthode dynamique. Si le délégué représentant la méthode doit être lié à un objet, le premier paramètre doit correspondre au type auquel le délégué est lié. Dans cet exemple, il existe deux paramètres, de type
Example
et de typeint
(Integer
en Visual Basic).Type[] methodArgs2 = { typeof(Example), typeof(int) };
Dim methodArgs2 As Type() = _ {GetType(Example), GetType(Integer)}
Créer un DynamicMethod. Dans cet exemple, la méthode n’a aucun nom. Le type de la valeur de retour est spécifié comme
int
(Integer
en Visual Basic). La méthode a accès aux membres privés et protégés de laExample
classe.DynamicMethod multiplyHidden = new DynamicMethod( "", typeof(int), methodArgs2, typeof(Example));
Dim multiplyPrivate As New DynamicMethod( _ "", _ GetType(Integer), _ methodArgs2, _ GetType(Example))
Émettez le corps de la méthode. Dans cet exemple, un ILGenerator objet est utilisé pour émettre le langage intermédiaire commun (CIL). Vous pouvez également utiliser un DynamicILInfo objet conjointement avec des générateurs de code non managés pour émettre le corps de la méthode pour un DynamicMethod.
La bibliothèque CIL de cet exemple charge le premier argument, qui est une instance de la
Example
classe, et l’utilise pour charger la valeur d’un champ d’instance privée de typeint
. Le deuxième argument est chargé et les deux nombres sont multipliés. Si le résultat est supérieurint
à , la valeur est tronquée et les bits les plus significatifs sont ignorés. La méthode retourne, avec la valeur de retour sur la pile.ILGenerator ilMH = multiplyHidden.GetILGenerator(); ilMH.Emit(OpCodes.Ldarg_0); FieldInfo testInfo = typeof(Example).GetField("test", BindingFlags.NonPublic | BindingFlags.Instance); ilMH.Emit(OpCodes.Ldfld, testInfo); ilMH.Emit(OpCodes.Ldarg_1); ilMH.Emit(OpCodes.Mul); ilMH.Emit(OpCodes.Ret);
Dim ilMP As ILGenerator = multiplyPrivate.GetILGenerator() ilMP.Emit(OpCodes.Ldarg_0) Dim testInfo As FieldInfo = _ GetType(Example).GetField("test", _ BindingFlags.NonPublic Or BindingFlags.Instance) ilMP.Emit(OpCodes.Ldfld, testInfo) ilMP.Emit(OpCodes.Ldarg_1) ilMP.Emit(OpCodes.Mul) ilMP.Emit(OpCodes.Ret)
Créez une instance du délégué (déclaré à l’étape 1) qui représente la méthode dynamique en appelant la CreateDelegate(Type, Object) surcharge de méthode. La création du délégué termine la méthode et toutes les autres tentatives de modification de la méthode( par exemple, l’ajout d’autres fichiers CIL) sont ignorées.
Remarque
Vous pouvez appeler la CreateDelegate méthode plusieurs fois pour créer des délégués liés à d’autres instances du type cible.
Le code suivant lie la méthode à une nouvelle instance de la classe dont le
Example
champ de test privé est défini sur 42. Autrement dit, chaque fois que le délégué est appelé, l’instance deExample
est passée en tant que premier paramètre de la méthode.Le délégué
OneParameter
est utilisé, car le premier paramètre de la méthode reçoit toujours l’instance deExample
. Lorsque le délégué est appelé, seul le deuxième paramètre est requis.OneParameter<int, int> invoke = (OneParameter<int, int>) multiplyHidden.CreateDelegate( typeof(OneParameter<int, int>), new Example(42) ); Console.WriteLine($"3 * test = {invoke(3)}");
Dim invoke As OneParameter(Of Integer, Integer) = _ CType( _ multiplyPrivate.CreateDelegate( _ GetType(OneParameter(Of Integer, Integer)), _ new Example(42) _ ), _ OneParameter(Of Integer, Integer) _ ) Console.WriteLine("3 * test = {0}", invoke(3))
Exemple :
L’exemple de code suivant illustre une méthode dynamique simple et une méthode dynamique liée à une instance d’une classe.
La méthode dynamique simple prend un argument, un entier 32 bits et retourne le carré 64 bits de cet entier. Un délégué générique est utilisé pour appeler la méthode.
La deuxième méthode dynamique a deux paramètres, de type Example
et de type int
(Integer
en Visual Basic). Lorsque la méthode dynamique a été créée, elle est liée à une instance de Example
, à l’aide d’un délégué générique qui a un argument de type int
. Le délégué n’a pas d’argument de type Example
, car le premier paramètre de la méthode reçoit toujours l’instance liée de Example
. Lorsque le délégué est appelé, seul l’argument int
est fourni. Cette méthode dynamique accède à un champ privé de la Example
classe et retourne le produit du champ privé et de l’argument int
.
L’exemple de code définit des délégués qui peuvent être utilisés pour exécuter les méthodes.
using System;
using System.Reflection;
using System.Reflection.Emit;
public class Example
{
// The following constructor and private field are used to
// demonstrate a method bound to an object.
private int test;
public Example(int test) { this.test = test; }
// Declare delegates that can be used to execute the completed
// SquareIt dynamic method. The OneParameter delegate can be
// used to execute any method with one parameter and a return
// value, or a method with two parameters and a return value
// if the delegate is bound to an object.
//
private delegate long SquareItInvoker(int input);
private delegate TReturn OneParameter<TReturn, TParameter0>
(TParameter0 p0);
public static void Main()
{
// Example 1: A simple dynamic method.
//
// Create an array that specifies the parameter types for the
// dynamic method. In this example the only parameter is an
// int, so the array has only one element.
//
Type[] methodArgs = {typeof(int)};
// Create a DynamicMethod. In this example the method is
// named SquareIt. It is not necessary to give dynamic
// methods names. They cannot be invoked by name, and two
// dynamic methods can have the same name. However, the
// name appears in calls stacks and can be useful for
// debugging.
//
// In this example the return type of the dynamic method
// is long. The method is associated with the module that
// contains the Example class. Any loaded module could be
// specified. The dynamic method is like a module-level
// static method.
//
DynamicMethod squareIt = new DynamicMethod(
"SquareIt",
typeof(long),
methodArgs,
typeof(Example).Module);
// Emit the method body. In this example ILGenerator is used
// to emit the MSIL. DynamicMethod has an associated type
// DynamicILInfo that can be used in conjunction with
// unmanaged code generators.
//
// The MSIL loads the argument, which is an int, onto the
// stack, converts the int to a long, duplicates the top
// item on the stack, and multiplies the top two items on the
// stack. This leaves the squared number on the stack, and
// all the method has to do is return.
//
ILGenerator il = squareIt.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Conv_I8);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Mul);
il.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method.
// Creating the delegate completes the method, and any further
// attempts to change the method (for example, by adding more
// MSIL) are ignored. The following code uses a generic
// delegate that can produce delegate types matching any
// single-parameter method that has a return type.
//
OneParameter<long, int> invokeSquareIt =
(OneParameter<long, int>)
squareIt.CreateDelegate(typeof(OneParameter<long, int>));
Console.WriteLine($"123456789 squared = {invokeSquareIt(123456789)}");
// Example 2: A dynamic method bound to an instance.
//
// Create an array that specifies the parameter types for a
// dynamic method. If the delegate representing the method
// is to be bound to an object, the first parameter must
// match the type the delegate is bound to. In the following
// code the bound instance is of the Example class.
//
Type[] methodArgs2 = { typeof(Example), typeof(int) };
// Create a DynamicMethod. In this example the method has no
// name. The return type of the method is int. The method
// has access to the protected and private data of the
// Example class.
//
DynamicMethod multiplyHidden = new DynamicMethod(
"",
typeof(int),
methodArgs2,
typeof(Example));
// Emit the method body. In this example ILGenerator is used
// to emit the MSIL. DynamicMethod has an associated type
// DynamicILInfo that can be used in conjunction with
// unmanaged code generators.
//
// The MSIL loads the first argument, which is an instance of
// the Example class, and uses it to load the value of a
// private instance field of type int. The second argument is
// loaded, and the two numbers are multiplied. If the result
// is larger than int, the value is truncated and the most
// significant bits are discarded. The method returns, with
// the return value on the stack.
//
ILGenerator ilMH = multiplyHidden.GetILGenerator();
ilMH.Emit(OpCodes.Ldarg_0);
FieldInfo testInfo = typeof(Example).GetField("test",
BindingFlags.NonPublic | BindingFlags.Instance);
ilMH.Emit(OpCodes.Ldfld, testInfo);
ilMH.Emit(OpCodes.Ldarg_1);
ilMH.Emit(OpCodes.Mul);
ilMH.Emit(OpCodes.Ret);
// Create a delegate that represents the dynamic method.
// Creating the delegate completes the method, and any further
// attempts to change the method — for example, by adding more
// MSIL — are ignored.
//
// The following code binds the method to a new instance
// of the Example class whose private test field is set to 42.
// That is, each time the delegate is invoked the instance of
// Example is passed to the first parameter of the method.
//
// The delegate OneParameter is used, because the first
// parameter of the method receives the instance of Example.
// When the delegate is invoked, only the second parameter is
// required.
//
OneParameter<int, int> invoke = (OneParameter<int, int>)
multiplyHidden.CreateDelegate(
typeof(OneParameter<int, int>),
new Example(42)
);
Console.WriteLine($"3 * test = {invoke(3)}");
}
}
/* This code example produces the following output:
123456789 squared = 15241578750190521
3 * test = 126
*/
Imports System.Reflection
Imports System.Reflection.Emit
Public Class Example
' The following constructor and private field are used to
' demonstrate a method bound to an object.
'
Private test As Integer
Public Sub New(ByVal test As Integer)
Me.test = test
End Sub
' Declare delegates that can be used to execute the completed
' SquareIt dynamic method. The OneParameter delegate can be
' used to execute any method with one parameter and a return
' value, or a method with two parameters and a return value
' if the delegate is bound to an object.
'
Private Delegate Function _
SquareItInvoker(ByVal input As Integer) As Long
Private Delegate Function _
OneParameter(Of TReturn, TParameter0) _
(ByVal p0 As TParameter0) As TReturn
Public Shared Sub Main()
' Example 1: A simple dynamic method.
'
' Create an array that specifies the parameter types for the
' dynamic method. In this example the only parameter is an
' Integer, so the array has only one element.
'
Dim methodArgs As Type() = {GetType(Integer)}
' Create a DynamicMethod. In this example the method is
' named SquareIt. It is not necessary to give dynamic
' methods names. They cannot be invoked by name, and two
' dynamic methods can have the same name. However, the
' name appears in calls stacks and can be useful for
' debugging.
'
' In this example the return type of the dynamic method
' is Long. The method is associated with the module that
' contains the Example class. Any loaded module could be
' specified. The dynamic method is like a module-level
' Shared method.
'
Dim squareIt As New DynamicMethod( _
"SquareIt", _
GetType(Long), _
methodArgs, _
GetType(Example).Module)
' Emit the method body. In this example ILGenerator is used
' to emit the MSIL. DynamicMethod has an associated type
' DynamicILInfo that can be used in conjunction with
' unmanaged code generators.
'
' The MSIL loads the argument, which is an Integer, onto the
' stack, converts the Integer to a Long, duplicates the top
' item on the stack, and multiplies the top two items on the
' stack. This leaves the squared number on the stack, and
' all the method has to do is return.
'
Dim il As ILGenerator = squareIt.GetILGenerator()
il.Emit(OpCodes.Ldarg_0)
il.Emit(OpCodes.Conv_I8)
il.Emit(OpCodes.Dup)
il.Emit(OpCodes.Mul)
il.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method.
' Creating the delegate completes the method, and any further
' attempts to change the method (for example, by adding more
' MSIL) are ignored. The following code uses a generic
' delegate that can produce delegate types matching any
' single-parameter method that has a return type.
'
Dim invokeSquareIt As OneParameter(Of Long, Integer) = _
CType( _
squareIt.CreateDelegate( _
GetType(OneParameter(Of Long, Integer))), _
OneParameter(Of Long, Integer) _
)
Console.WriteLine("123456789 squared = {0}", _
invokeSquareIt(123456789))
' Example 2: A dynamic method bound to an instance.
'
' Create an array that specifies the parameter types for a
' dynamic method. If the delegate representing the method
' is to be bound to an object, the first parameter must
' match the type the delegate is bound to. In the following
' code the bound instance is of the Example class.
'
Dim methodArgs2 As Type() = _
{GetType(Example), GetType(Integer)}
' Create a DynamicMethod. In this example the method has no
' name. The return type of the method is Integer. The method
' has access to the protected and private members of the
' Example class.
'
Dim multiplyPrivate As New DynamicMethod( _
"", _
GetType(Integer), _
methodArgs2, _
GetType(Example))
' Emit the method body. In this example ILGenerator is used
' to emit the MSIL. DynamicMethod has an associated type
' DynamicILInfo that can be used in conjunction with
' unmanaged code generators.
'
' The MSIL loads the first argument, which is an instance of
' the Example class, and uses it to load the value of a
' private instance field of type Integer. The second argument
' is loaded, and the two numbers are multiplied. If the result
' is larger than Integer, the value is truncated and the most
' significant bits are discarded. The method returns, with
' the return value on the stack.
'
Dim ilMP As ILGenerator = multiplyPrivate.GetILGenerator()
ilMP.Emit(OpCodes.Ldarg_0)
Dim testInfo As FieldInfo = _
GetType(Example).GetField("test", _
BindingFlags.NonPublic Or BindingFlags.Instance)
ilMP.Emit(OpCodes.Ldfld, testInfo)
ilMP.Emit(OpCodes.Ldarg_1)
ilMP.Emit(OpCodes.Mul)
ilMP.Emit(OpCodes.Ret)
' Create a delegate that represents the dynamic method.
' Creating the delegate completes the method, and any further
' attempts to change the method for example, by adding more
' MSIL are ignored.
'
' The following code binds the method to a new instance
' of the Example class whose private test field is set to 42.
' That is, each time the delegate is invoked the instance of
' Example is passed to the first parameter of the method.
'
' The delegate OneParameter is used, because the first
' parameter of the method receives the instance of Example.
' When the delegate is invoked, only the second parameter is
' required.
'
Dim invoke As OneParameter(Of Integer, Integer) = _
CType( _
multiplyPrivate.CreateDelegate( _
GetType(OneParameter(Of Integer, Integer)), _
new Example(42) _
), _
OneParameter(Of Integer, Integer) _
)
Console.WriteLine("3 * test = {0}", invoke(3))
End Sub
End Class
' This code example produces the following output:
'
'123456789 squared = 15241578750190521
'3 * test = 126
'