ILGenerator.Emit Metodo
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Inserisce un'istruzione nel flusso MSIL (Microsoft Intermediate Language) per il compilatore JIT (Just-In-Time).
Overload
| Nome | Descrizione |
|---|---|
| Emit(OpCode, LocalBuilder) |
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dall'indice della variabile locale specificata. |
| Emit(OpCode, Type) |
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dal token di metadati per il tipo specificato. |
| Emit(OpCode, String) |
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dal token di metadati per la stringa specificata. |
| Emit(OpCode, Single) |
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, SByte) |
Inserisce l'istruzione e l'argomento carattere specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, FieldInfo) |
Inserisce l'istruzione e il token di metadati specificati per il campo specificato nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, SignatureHelper) |
Inserisce l'istruzione specificata e un token di firma nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, Label[]) |
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft e lascia spazio per includere un'etichetta al termine delle correzioni. |
| Emit(OpCode, MethodInfo) |
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dal token di metadati per il metodo specificato. |
| Emit(OpCode, ConstructorInfo) |
Inserisce l'istruzione e il token di metadati specificati per il costruttore specificato nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, Int64) |
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, Int32) |
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, Int16) |
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, Double) |
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode, Byte) |
Inserisce l'istruzione e l'argomento carattere specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft. |
| Emit(OpCode) |
Inserisce l'istruzione specificata nel flusso di istruzioni. |
| Emit(OpCode, Label) |
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft e lascia spazio per includere un'etichetta al termine delle correzioni. |
Emit(OpCode, LocalBuilder)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dall'indice della variabile locale specificata.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::LocalBuilder ^ local);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::LocalBuilder ^ local);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
Public MustOverride Sub Emit (opcode As OpCode, local As LocalBuilder)
Public Overridable Sub Emit (opcode As OpCode, local As LocalBuilder)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- local
- LocalBuilder
Variabile locale.
Eccezioni
Il metodo padre del local parametro non corrisponde al metodo associato a questo ILGeneratoroggetto .
local è null.
opcode è un'istruzione a byte singolo e local rappresenta una variabile locale con un indice maggiore di Byte.MaxValue.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, Type)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dal token di metadati per il tipo specificato.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, Type ^ cls);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, Type ^ cls);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, Type cls);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, Type cls);
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
override this.Emit : System.Reflection.Emit.OpCode * Type -> unit
Public MustOverride Sub Emit (opcode As OpCode, cls As Type)
Public Overridable Sub Emit (opcode As OpCode, cls As Type)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso.
- cls
- Type
Un oggetto Type.
Eccezioni
cls è null.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes . Il percorso di cls viene registrato in modo che il token possa essere patchato se necessario quando il modulo viene salvato in modo permanente in un file eseguibile portabile (PE).
Si applica a
Emit(OpCode, String)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dal token di metadati per la stringa specificata.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, string str);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, string str);
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
override this.Emit : System.Reflection.Emit.OpCode * string -> unit
Public MustOverride Sub Emit (opcode As OpCode, str As String)
Public Overridable Sub Emit (opcode As OpCode, str As String)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- str
- String
Oggetto String da generare.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes . Il percorso di str viene registrato per correzioni future se il modulo è persistente in un file eseguibile portabile (PE).
Si applica a
Emit(OpCode, Single)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, float arg);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, float arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, float arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, float arg);
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
override this.Emit : System.Reflection.Emit.OpCode * single -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Single)
Public Overridable Sub Emit (opcode As OpCode, arg As Single)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, SByte)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Importante
Questa API non è conforme a CLS.
Inserisce l'istruzione e l'argomento carattere specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
void Emit(System::Reflection::Emit::OpCode opcode, System::SByte arg);
[System.CLSCompliant(false)]
public void Emit(System.Reflection.Emit.OpCode opcode, sbyte arg);
[<System.CLSCompliant(false)>]
member this.Emit : System.Reflection.Emit.OpCode * sbyte -> unit
Public Sub Emit (opcode As OpCode, arg As SByte)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso.
- arg
- SByte
Argomento carattere inserito nel flusso immediatamente dopo l'istruzione.
- Attributi
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, FieldInfo)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e il token di metadati specificati per il campo specificato nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::FieldInfo ^ field);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::FieldInfo ^ field);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
Public MustOverride Sub Emit (opcode As OpCode, field As FieldInfo)
Public Overridable Sub Emit (opcode As OpCode, field As FieldInfo)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- field
- FieldInfo
Oggetto FieldInfo che rappresenta un campo.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes . Il percorso di viene registrato in modo che il flusso di field istruzioni possa essere patchato se necessario quando il modulo viene salvato in modo permanente in un file eseguibile portabile (PE).
Si applica a
Emit(OpCode, SignatureHelper)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata e un token di firma nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::SignatureHelper ^ signature);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::SignatureHelper ^ signature);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
Public MustOverride Sub Emit (opcode As OpCode, signature As SignatureHelper)
Public Overridable Sub Emit (opcode As OpCode, signature As SignatureHelper)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- signature
- SignatureHelper
Helper per la costruzione di un token di firma.
Eccezioni
signature è null.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, Label[])
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft e lascia spazio per includere un'etichetta al termine delle correzioni.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, cli::array <System::Reflection::Emit::Label> ^ labels);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, cli::array <System::Reflection::Emit::Label> ^ labels);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
Public MustOverride Sub Emit (opcode As OpCode, labels As Label())
Public Overridable Sub Emit (opcode As OpCode, labels As Label())
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- labels
- Label[]
Matrice di oggetti etichetta a cui creare un ramo da questa posizione. Verranno usate tutte le etichette.
Esempio
L'esempio di codice seguente illustra la creazione di un metodo dinamico con una tabella jump. La tabella di salto viene compilata usando una matrice di Label.
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
class DynamicJumpTableDemo
{
public static Type BuildMyType()
{
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
"MyJumpTableDemo");
TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
TypeAttributes.Public);
MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(string),
new Type[] {typeof(int)});
ILGenerator myIL = myMthdBuilder.GetILGenerator();
Label defaultCase = myIL.DefineLabel();
Label endOfMethod = myIL.DefineLabel();
// We are initializing our jump table. Note that the labels
// will be placed later using the MarkLabel method.
Label[] jumpTable = new Label[] { myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel() };
// arg0, the number we passed, is pushed onto the stack.
// In this case, due to the design of the code sample,
// the value pushed onto the stack happens to match the
// index of the label (in IL terms, the index of the offset
// in the jump table). If this is not the case, such as
// when switching based on non-integer values, rules for the correspondence
// between the possible case values and each index of the offsets
// must be established outside of the ILGenerator.Emit calls,
// much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0);
myIL.Emit(OpCodes.Switch, jumpTable);
// Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase);
// Case arg0 = 0
myIL.MarkLabel(jumpTable[0]);
myIL.Emit(OpCodes.Ldstr, "are no bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 1
myIL.MarkLabel(jumpTable[1]);
myIL.Emit(OpCodes.Ldstr, "is one banana");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 2
myIL.MarkLabel(jumpTable[2]);
myIL.Emit(OpCodes.Ldstr, "are two bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 3
myIL.MarkLabel(jumpTable[3]);
myIL.Emit(OpCodes.Ldstr, "are three bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 4
myIL.MarkLabel(jumpTable[4]);
myIL.Emit(OpCodes.Ldstr, "are four bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Default case
myIL.MarkLabel(defaultCase);
myIL.Emit(OpCodes.Ldstr, "are many bananas");
myIL.MarkLabel(endOfMethod);
myIL.Emit(OpCodes.Ret);
return myTypeBuilder.CreateType();
}
public static void Main()
{
Type myType = BuildMyType();
Console.Write("Enter an integer between 0 and 5: ");
int theValue = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("---");
Object myInstance = Activator.CreateInstance(myType, new object[0]);
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
BindingFlags.InvokeMethod,
null,
myInstance,
new object[] {theValue}));
}
}
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
_
Class DynamicJumpTableDemo
Public Shared Function BuildMyType() As Type
Dim myDomain As AppDomain = Thread.GetDomain()
Dim myAsmName As New AssemblyName()
myAsmName.Name = "MyDynamicAssembly"
Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.Run)
Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
TypeAttributes.Public)
Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
MethodAttributes.Public Or MethodAttributes.Static, _
GetType(String), New Type() {GetType(Integer)})
Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
Dim defaultCase As Label = myIL.DefineLabel()
Dim endOfMethod As Label = myIL.DefineLabel()
' We are initializing our jump table. Note that the labels
' will be placed later using the MarkLabel method.
Dim jumpTable() As Label = {myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel()}
' arg0, the number we passed, is pushed onto the stack.
' In this case, due to the design of the code sample,
' the value pushed onto the stack happens to match the
' index of the label (in IL terms, the index of the offset
' in the jump table). If this is not the case, such as
' when switching based on non-integer values, rules for the correspondence
' between the possible case values and each index of the offsets
' must be established outside of the ILGenerator.Emit calls,
' much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0)
myIL.Emit(OpCodes.Switch, jumpTable)
' Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase)
' Case arg0 = 0
myIL.MarkLabel(jumpTable(0))
myIL.Emit(OpCodes.Ldstr, "are no bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 1
myIL.MarkLabel(jumpTable(1))
myIL.Emit(OpCodes.Ldstr, "is one banana")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 2
myIL.MarkLabel(jumpTable(2))
myIL.Emit(OpCodes.Ldstr, "are two bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 3
myIL.MarkLabel(jumpTable(3))
myIL.Emit(OpCodes.Ldstr, "are three bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 4
myIL.MarkLabel(jumpTable(4))
myIL.Emit(OpCodes.Ldstr, "are four bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Default case
myIL.MarkLabel(defaultCase)
myIL.Emit(OpCodes.Ldstr, "are many bananas")
myIL.MarkLabel(endOfMethod)
myIL.Emit(OpCodes.Ret)
Return myTypeBuilder.CreateType()
End Function 'BuildMyType
Public Shared Sub Main()
Dim myType As Type = BuildMyType()
Console.Write("Enter an integer between 0 and 5: ")
Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
Console.WriteLine("---")
Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
BindingFlags.InvokeMethod, Nothing, _
myInstance, New Object() {theValue}))
End Sub
End Class
Commenti
Genera una tabella switch.
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Le etichette vengono create usando DefineLabel e la relativa posizione all'interno del flusso è fissa tramite MarkLabel. Se viene usata un'istruzione a byte singolo, l'etichetta può rappresentare un salto di al massimo 127 byte lungo il flusso.
opcode deve rappresentare un'istruzione di ramo. Poiché i rami sono istruzioni relative, label verranno sostituiti con l'offset corretto nel ramo durante il processo di correzione.
Si applica a
Emit(OpCode, MethodInfo)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft seguito dal token di metadati per il metodo specificato.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::MethodInfo ^ meth);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::MethodInfo ^ meth);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
Public MustOverride Sub Emit (opcode As OpCode, meth As MethodInfo)
Public Overridable Sub Emit (opcode As OpCode, meth As MethodInfo)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- meth
- MethodInfo
Oggetto MethodInfo che rappresenta un metodo.
Eccezioni
meth è null.
meth è un metodo generico per il quale la IsGenericMethodDefinition proprietà è false.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Il percorso di viene registrato in modo che il flusso di meth istruzioni possa essere patchato se necessario quando il modulo viene salvato in modo permanente in un file eseguibile portabile (PE).
Se meth rappresenta un metodo generico, deve essere una definizione di metodo generico. Ovvero, la proprietà MethodInfo.IsGenericMethodDefinition deve essere true.
Si applica a
Emit(OpCode, ConstructorInfo)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e il token di metadati specificati per il costruttore specificato nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::ConstructorInfo ^ con);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::ConstructorInfo ^ con);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
[System.Runtime.InteropServices.ComVisible(true)]
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
[<System.Runtime.InteropServices.ComVisible(true)>]
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
Public MustOverride Sub Emit (opcode As OpCode, con As ConstructorInfo)
Public Overridable Sub Emit (opcode As OpCode, con As ConstructorInfo)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- con
- ConstructorInfo
Oggetto ConstructorInfo che rappresenta un costruttore.
- Attributi
Eccezioni
con è null.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Il percorso di viene registrato in modo che il flusso di con istruzioni possa essere patchato se necessario quando il modulo viene salvato in modo permanente in un file eseguibile portabile (PE).
Si applica a
Emit(OpCode, Int64)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, long arg);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, long arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, long arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, long arg);
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int64 -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Long)
Public Overridable Sub Emit (opcode As OpCode, arg As Long)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso.
- arg
- Int64
Argomento numerico inserito nel flusso immediatamente dopo l'istruzione.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, Int32)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, int arg);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, int arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, int arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, int arg);
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
override this.Emit : System.Reflection.Emit.OpCode * int -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Integer)
Public Overridable Sub Emit (opcode As OpCode, arg As Integer)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso.
- arg
- Int32
Argomento numerico inserito nel flusso immediatamente dopo l'istruzione.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, Int16)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, short arg);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, short arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, short arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, short arg);
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int16 -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Short)
Public Overridable Sub Emit (opcode As OpCode, arg As Short)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- arg
- Int16
Argomento Int inserito nel flusso immediatamente dopo l'istruzione.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, Double)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e l'argomento numerico specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, double arg);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, double arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, double arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, double arg);
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
override this.Emit : System.Reflection.Emit.OpCode * double -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Double)
Public Overridable Sub Emit (opcode As OpCode, arg As Double)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso. Definito nell'enumerazione OpCodes .
- arg
- Double
Argomento numerico inserito nel flusso immediatamente dopo l'istruzione.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode, Byte)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione e l'argomento carattere specificati nel flusso di istruzioni MSIL (Intermediate Language) Microsoft.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, byte arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, byte arg);
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
override this.Emit : System.Reflection.Emit.OpCode * byte -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Byte)
Public Overridable Sub Emit (opcode As OpCode, arg As Byte)
Parametri
- opcode
- OpCode
Istruzione MSIL da inserire nel flusso.
- arg
- Byte
Argomento carattere inserito nel flusso immediatamente dopo l'istruzione.
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Si applica a
Emit(OpCode)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso di istruzioni.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode);
public abstract void Emit(System.Reflection.Emit.OpCode opcode);
public virtual void Emit(System.Reflection.Emit.OpCode opcode);
abstract member Emit : System.Reflection.Emit.OpCode -> unit
abstract member Emit : System.Reflection.Emit.OpCode -> unit
override this.Emit : System.Reflection.Emit.OpCode -> unit
Public MustOverride Sub Emit (opcode As OpCode)
Public Overridable Sub Emit (opcode As OpCode)
Parametri
- opcode
- OpCode
Istruzione Microsoft MSIL (Intermediate Language) da inserire nel flusso.
Esempio
L'esempio di codice seguente illustra l'uso di Emit per generare l'output MSIL tramite un'istanza di ILGenerator.
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
class DynamicJumpTableDemo
{
public static Type BuildMyType()
{
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
"MyJumpTableDemo");
TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
TypeAttributes.Public);
MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(string),
new Type[] {typeof(int)});
ILGenerator myIL = myMthdBuilder.GetILGenerator();
Label defaultCase = myIL.DefineLabel();
Label endOfMethod = myIL.DefineLabel();
// We are initializing our jump table. Note that the labels
// will be placed later using the MarkLabel method.
Label[] jumpTable = new Label[] { myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel() };
// arg0, the number we passed, is pushed onto the stack.
// In this case, due to the design of the code sample,
// the value pushed onto the stack happens to match the
// index of the label (in IL terms, the index of the offset
// in the jump table). If this is not the case, such as
// when switching based on non-integer values, rules for the correspondence
// between the possible case values and each index of the offsets
// must be established outside of the ILGenerator.Emit calls,
// much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0);
myIL.Emit(OpCodes.Switch, jumpTable);
// Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase);
// Case arg0 = 0
myIL.MarkLabel(jumpTable[0]);
myIL.Emit(OpCodes.Ldstr, "are no bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 1
myIL.MarkLabel(jumpTable[1]);
myIL.Emit(OpCodes.Ldstr, "is one banana");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 2
myIL.MarkLabel(jumpTable[2]);
myIL.Emit(OpCodes.Ldstr, "are two bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 3
myIL.MarkLabel(jumpTable[3]);
myIL.Emit(OpCodes.Ldstr, "are three bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 4
myIL.MarkLabel(jumpTable[4]);
myIL.Emit(OpCodes.Ldstr, "are four bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Default case
myIL.MarkLabel(defaultCase);
myIL.Emit(OpCodes.Ldstr, "are many bananas");
myIL.MarkLabel(endOfMethod);
myIL.Emit(OpCodes.Ret);
return myTypeBuilder.CreateType();
}
public static void Main()
{
Type myType = BuildMyType();
Console.Write("Enter an integer between 0 and 5: ");
int theValue = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("---");
Object myInstance = Activator.CreateInstance(myType, new object[0]);
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
BindingFlags.InvokeMethod,
null,
myInstance,
new object[] {theValue}));
}
}
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
_
Class DynamicJumpTableDemo
Public Shared Function BuildMyType() As Type
Dim myDomain As AppDomain = Thread.GetDomain()
Dim myAsmName As New AssemblyName()
myAsmName.Name = "MyDynamicAssembly"
Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.Run)
Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
TypeAttributes.Public)
Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
MethodAttributes.Public Or MethodAttributes.Static, _
GetType(String), New Type() {GetType(Integer)})
Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
Dim defaultCase As Label = myIL.DefineLabel()
Dim endOfMethod As Label = myIL.DefineLabel()
' We are initializing our jump table. Note that the labels
' will be placed later using the MarkLabel method.
Dim jumpTable() As Label = {myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel()}
' arg0, the number we passed, is pushed onto the stack.
' In this case, due to the design of the code sample,
' the value pushed onto the stack happens to match the
' index of the label (in IL terms, the index of the offset
' in the jump table). If this is not the case, such as
' when switching based on non-integer values, rules for the correspondence
' between the possible case values and each index of the offsets
' must be established outside of the ILGenerator.Emit calls,
' much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0)
myIL.Emit(OpCodes.Switch, jumpTable)
' Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase)
' Case arg0 = 0
myIL.MarkLabel(jumpTable(0))
myIL.Emit(OpCodes.Ldstr, "are no bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 1
myIL.MarkLabel(jumpTable(1))
myIL.Emit(OpCodes.Ldstr, "is one banana")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 2
myIL.MarkLabel(jumpTable(2))
myIL.Emit(OpCodes.Ldstr, "are two bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 3
myIL.MarkLabel(jumpTable(3))
myIL.Emit(OpCodes.Ldstr, "are three bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 4
myIL.MarkLabel(jumpTable(4))
myIL.Emit(OpCodes.Ldstr, "are four bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Default case
myIL.MarkLabel(defaultCase)
myIL.Emit(OpCodes.Ldstr, "are many bananas")
myIL.MarkLabel(endOfMethod)
myIL.Emit(OpCodes.Ret)
Return myTypeBuilder.CreateType()
End Function 'BuildMyType
Public Shared Sub Main()
Dim myType As Type = BuildMyType()
Console.Write("Enter an integer between 0 and 5: ")
Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
Console.WriteLine("---")
Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
BindingFlags.InvokeMethod, Nothing, _
myInstance, New Object() {theValue}))
End Sub
End Class
Commenti
Se il opcode parametro richiede un argomento, il chiamante deve assicurarsi che la lunghezza dell'argomento corrisponda alla lunghezza del parametro dichiarato. In caso contrario, i risultati saranno imprevedibili. Ad esempio, se l'istruzione Emit richiede un operando a 2 byte e il chiamante fornisce un operando a 4 byte, il runtime genererà due byte aggiuntivi al flusso di istruzioni. Questi byte aggiuntivi saranno Nop istruzioni.
I valori delle istruzioni sono definiti in OpCodes.
Si applica a
Emit(OpCode, Label)
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
- Origine:
- ILGenerator.cs
Inserisce l'istruzione specificata nel flusso MSIL (Intermediate Language) Microsoft e lascia spazio per includere un'etichetta al termine delle correzioni.
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::Label label);
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::Label label);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
Public MustOverride Sub Emit (opcode As OpCode, label As Label)
Public Overridable Sub Emit (opcode As OpCode, label As Label)
Parametri
- opcode
- OpCode
Istruzione MSIL da generare nel flusso.
- label
- Label
Etichetta a cui creare un ramo da questa posizione.
Esempio
L'esempio di codice seguente illustra la creazione di un metodo dinamico con una tabella jump. La tabella di salto viene compilata usando una matrice di Label.
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
class DynamicJumpTableDemo
{
public static Type BuildMyType()
{
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
"MyJumpTableDemo");
TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
TypeAttributes.Public);
MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(string),
new Type[] {typeof(int)});
ILGenerator myIL = myMthdBuilder.GetILGenerator();
Label defaultCase = myIL.DefineLabel();
Label endOfMethod = myIL.DefineLabel();
// We are initializing our jump table. Note that the labels
// will be placed later using the MarkLabel method.
Label[] jumpTable = new Label[] { myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel() };
// arg0, the number we passed, is pushed onto the stack.
// In this case, due to the design of the code sample,
// the value pushed onto the stack happens to match the
// index of the label (in IL terms, the index of the offset
// in the jump table). If this is not the case, such as
// when switching based on non-integer values, rules for the correspondence
// between the possible case values and each index of the offsets
// must be established outside of the ILGenerator.Emit calls,
// much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0);
myIL.Emit(OpCodes.Switch, jumpTable);
// Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase);
// Case arg0 = 0
myIL.MarkLabel(jumpTable[0]);
myIL.Emit(OpCodes.Ldstr, "are no bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 1
myIL.MarkLabel(jumpTable[1]);
myIL.Emit(OpCodes.Ldstr, "is one banana");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 2
myIL.MarkLabel(jumpTable[2]);
myIL.Emit(OpCodes.Ldstr, "are two bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 3
myIL.MarkLabel(jumpTable[3]);
myIL.Emit(OpCodes.Ldstr, "are three bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 4
myIL.MarkLabel(jumpTable[4]);
myIL.Emit(OpCodes.Ldstr, "are four bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Default case
myIL.MarkLabel(defaultCase);
myIL.Emit(OpCodes.Ldstr, "are many bananas");
myIL.MarkLabel(endOfMethod);
myIL.Emit(OpCodes.Ret);
return myTypeBuilder.CreateType();
}
public static void Main()
{
Type myType = BuildMyType();
Console.Write("Enter an integer between 0 and 5: ");
int theValue = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("---");
Object myInstance = Activator.CreateInstance(myType, new object[0]);
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
BindingFlags.InvokeMethod,
null,
myInstance,
new object[] {theValue}));
}
}
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
_
Class DynamicJumpTableDemo
Public Shared Function BuildMyType() As Type
Dim myDomain As AppDomain = Thread.GetDomain()
Dim myAsmName As New AssemblyName()
myAsmName.Name = "MyDynamicAssembly"
Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.Run)
Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
TypeAttributes.Public)
Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
MethodAttributes.Public Or MethodAttributes.Static, _
GetType(String), New Type() {GetType(Integer)})
Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
Dim defaultCase As Label = myIL.DefineLabel()
Dim endOfMethod As Label = myIL.DefineLabel()
' We are initializing our jump table. Note that the labels
' will be placed later using the MarkLabel method.
Dim jumpTable() As Label = {myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel()}
' arg0, the number we passed, is pushed onto the stack.
' In this case, due to the design of the code sample,
' the value pushed onto the stack happens to match the
' index of the label (in IL terms, the index of the offset
' in the jump table). If this is not the case, such as
' when switching based on non-integer values, rules for the correspondence
' between the possible case values and each index of the offsets
' must be established outside of the ILGenerator.Emit calls,
' much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0)
myIL.Emit(OpCodes.Switch, jumpTable)
' Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase)
' Case arg0 = 0
myIL.MarkLabel(jumpTable(0))
myIL.Emit(OpCodes.Ldstr, "are no bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 1
myIL.MarkLabel(jumpTable(1))
myIL.Emit(OpCodes.Ldstr, "is one banana")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 2
myIL.MarkLabel(jumpTable(2))
myIL.Emit(OpCodes.Ldstr, "are two bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 3
myIL.MarkLabel(jumpTable(3))
myIL.Emit(OpCodes.Ldstr, "are three bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 4
myIL.MarkLabel(jumpTable(4))
myIL.Emit(OpCodes.Ldstr, "are four bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Default case
myIL.MarkLabel(defaultCase)
myIL.Emit(OpCodes.Ldstr, "are many bananas")
myIL.MarkLabel(endOfMethod)
myIL.Emit(OpCodes.Ret)
Return myTypeBuilder.CreateType()
End Function 'BuildMyType
Public Shared Sub Main()
Dim myType As Type = BuildMyType()
Console.Write("Enter an integer between 0 and 5: ")
Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
Console.WriteLine("---")
Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
BindingFlags.InvokeMethod, Nothing, _
myInstance, New Object() {theValue}))
End Sub
End Class
Commenti
I valori delle istruzioni vengono definiti nell'enumerazione OpCodes .
Le etichette vengono create usando DefineLabele la relativa posizione all'interno del flusso è fissa tramite MarkLabel. Se viene usata un'istruzione a byte singolo, l'etichetta può rappresentare un salto di al massimo 127 byte lungo il flusso.
opcode deve rappresentare un'istruzione di ramo. Poiché i rami sono istruzioni relative, label verranno sostituiti con l'offset corretto nel ramo durante il processo di correzione.