ILGenerator.Emit Metoda
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Umieszcza instrukcję w strumieniu języka Microsoft Intermediate Language (MSIL) dla kompilatora just in time (JIT).
Przeciążenia
| Nazwa | Opis |
|---|---|
| Emit(OpCode, LocalBuilder) |
Umieszcza określoną instrukcję na strumieniu języka Microsoft pośredniego (MSIL), po którym następuje indeks danej zmiennej lokalnej. |
| Emit(OpCode, Type) |
Umieszcza określoną instrukcję na strumieniu języka pośredniego Microsoft (MSIL), a następnie token metadanych dla danego typu. |
| Emit(OpCode, String) |
Umieszcza określoną instrukcję w strumieniu języka Microsoft pośredniego (MSIL), a następnie token metadanych dla danego ciągu. |
| Emit(OpCode, Single) |
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, SByte) |
Umieszcza określoną instrukcję i argument znaku na strumieniu instrukcji języka Microsoft pośredniego (MSIL). |
| Emit(OpCode, FieldInfo) |
Umieszcza określony token instrukcji i metadanych dla określonego pola na strumień instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, SignatureHelper) |
Umieszcza określoną instrukcję i token podpisu na strumieniu instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, Label[]) |
Umieszcza określoną instrukcję na strumieniu Microsoft języka pośredniego (MSIL) i pozostawia miejsce, aby dołączyć etykietę po zakończeniu poprawek. |
| Emit(OpCode, MethodInfo) |
Umieszcza określoną instrukcję na strumieniu języka Microsoft pośredniego (MSIL), a następnie token metadanych dla danej metody. |
| Emit(OpCode, ConstructorInfo) |
Umieszcza określony token instrukcji i metadanych dla określonego konstruktora na strumieniu instrukcji Microsoft pośredniego języka (MSIL). |
| Emit(OpCode, Int64) |
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, Int32) |
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, Int16) |
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, Double) |
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL). |
| Emit(OpCode, Byte) |
Umieszcza określoną instrukcję i argument znaku na strumieniu instrukcji języka Microsoft pośredniego (MSIL). |
| Emit(OpCode) |
Umieszcza określoną instrukcję na strumieniu instrukcji. |
| Emit(OpCode, Label) |
Umieszcza określoną instrukcję na strumieniu Microsoft języka pośredniego (MSIL) i pozostawia miejsce, aby dołączyć etykietę po zakończeniu poprawek. |
Emit(OpCode, LocalBuilder)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję na strumieniu języka Microsoft pośredniego (MSIL), po którym następuje indeks danej zmiennej lokalnej.
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- local
- LocalBuilder
Zmienna lokalna.
Wyjątki
Metoda nadrzędna parametru local jest niezgodna z metodą skojarzona z tym ILGeneratorparametrem .
Parametr local ma wartość null.
opcode jest instrukcją pojedynczego bajtu i local reprezentuje zmienną lokalną z indeksem większym niż Byte.MaxValue.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, Type)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję na strumieniu języka pośredniego Microsoft (MSIL), a następnie token metadanych dla danego typu.
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu.
- cls
- Type
Element Type.
Wyjątki
Parametr cls ma wartość null.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes . Lokalizacja cls elementu jest rejestrowana, aby token mógł zostać poprawiony w razie potrzeby podczas utrwalania modułu w przenośnym pliku wykonywalnym (PE).
Dotyczy
Emit(OpCode, String)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję w strumieniu języka Microsoft pośredniego (MSIL), a następnie token metadanych dla danego ciągu.
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- str
- String
Wartość String , która ma być emitowana.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes . Lokalizacja str elementu jest rejestrowana dla przyszłych poprawek, jeśli moduł jest utrwalany w przenośnym pliku wykonywalnym (PE).
Dotyczy
Emit(OpCode, Single)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, SByte)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Ważne
Ten interfejs API nie jest zgodny ze specyfikacją CLS.
Umieszcza określoną instrukcję i argument znaku na strumieniu instrukcji języka Microsoft pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu.
- arg
- SByte
Argument znaku został wypchnięty do strumienia bezpośrednio po instrukcji.
- Atrybuty
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, FieldInfo)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określony token instrukcji i metadanych dla określonego pola na strumień instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- field
- FieldInfo
Reprezentująca FieldInfo pole.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes . Lokalizacja field elementu jest rejestrowana tak, aby strumień instrukcji mógł zostać poprawiony w razie potrzeby podczas utrwalania modułu do przenośnego pliku wykonywalnego (PE).
Dotyczy
Emit(OpCode, SignatureHelper)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i token podpisu na strumieniu instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- signature
- SignatureHelper
Pomocnik do konstruowania tokenu podpisu.
Wyjątki
Parametr signature ma wartość null.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, Label[])
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję na strumieniu Microsoft języka pośredniego (MSIL) i pozostawia miejsce, aby dołączyć etykietę po zakończeniu poprawek.
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())
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- labels
- Label[]
Tablica obiektów etykiet, do których ma być rozgałęziona z tej lokalizacji. Zostaną użyte wszystkie etykiety.
Przykłady
Poniższy przykład kodu ilustruje tworzenie metody dynamicznej z tabelą skoków. Tabela skoków jest tworzona przy użyciu tablicy 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
Uwagi
Emituje tabelę przełączników.
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Etykiety są tworzone przy użyciu polecenia DefineLabel , a ich lokalizacja w strumieniu jest stała przy użyciu polecenia MarkLabel. Jeśli jest używana instrukcja jednobajtowa, etykieta może reprezentować skok co najwyżej 127 bajtów wzdłuż strumienia.
opcode musi reprezentować instrukcję gałęzi. Ponieważ gałęzie są instrukcjami względnymi, label zostaną zastąpione poprawnym przesunięciem do gałęzi podczas procesu naprawiania.
Dotyczy
Emit(OpCode, MethodInfo)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję na strumieniu języka Microsoft pośredniego (MSIL), a następnie token metadanych dla danej metody.
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- meth
- MethodInfo
Reprezentująca MethodInfo metodę.
Wyjątki
Parametr meth ma wartość null.
meth to metoda ogólna, dla której IsGenericMethodDefinition właściwość to false.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Lokalizacja meth elementu jest rejestrowana tak, aby strumień instrukcji mógł zostać poprawiony w razie potrzeby podczas utrwalania modułu do przenośnego pliku wykonywalnego (PE).
Jeśli meth reprezentuje metodę ogólną, musi być definicją metody ogólnej. Oznacza to, że jej właściwość MethodInfo.IsGenericMethodDefinition musi mieć wartość true.
Dotyczy
Emit(OpCode, ConstructorInfo)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określony token instrukcji i metadanych dla określonego konstruktora na strumieniu instrukcji Microsoft pośredniego języka (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- con
- ConstructorInfo
Reprezentujący ConstructorInfo konstruktor.
- Atrybuty
Wyjątki
Parametr con ma wartość null.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Lokalizacja con elementu jest rejestrowana tak, aby strumień instrukcji mógł zostać poprawiony w razie potrzeby podczas utrwalania modułu do przenośnego pliku wykonywalnego (PE).
Dotyczy
Emit(OpCode, Int64)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu.
- arg
- Int64
Argument liczbowy został wypchnięty do strumienia bezpośrednio po instrukcji.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, Int32)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu.
- arg
- Int32
Argument liczbowy został wypchnięty do strumienia bezpośrednio po instrukcji.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, Int16)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- arg
- Int16
Int Argument został wypchnięty do strumienia bezpośrednio po instrukcji.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, Double)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i argument liczbowy na strumieniu instrukcji Microsoft języka pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu. Zdefiniowano w wyliczenie OpCodes .
- arg
- Double
Argument liczbowy został wypchnięty do strumienia bezpośrednio po instrukcji.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode, Byte)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję i argument znaku na strumieniu instrukcji języka Microsoft pośredniego (MSIL).
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma zostać umieszczona na strumieniu.
- arg
- Byte
Argument znaku został wypchnięty do strumienia bezpośrednio po instrukcji.
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Dotyczy
Emit(OpCode)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję na strumieniu instrukcji.
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)
Parametry
- opcode
- OpCode
Instrukcja języka Microsoft pośredniego (MSIL) do umieszczenia na strumieniu.
Przykłady
W poniższym przykładzie kodu pokazano użycie metody Emit do generowania danych wyjściowych ILGeneratorMSIL za pośrednictwem wystąpienia klasy .
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
Uwagi
opcode Jeśli parametr wymaga argumentu, obiekt wywołujący musi upewnić się, że długość argumentu jest zgodna z długością zadeklarowanego parametru. W przeciwnym razie wyniki będą nieprzewidywalne. Jeśli na przykład instrukcja Emit wymaga operandu 2-bajtowego, a obiekt wywołujący dostarcza operand 4-bajtowy, środowisko uruchomieniowe emituje dwa dodatkowe bajty do strumienia instrukcji. Te dodatkowe bajty będą Nop instrukcjami.
Wartości instrukcji są definiowane w pliku OpCodes.
Dotyczy
Emit(OpCode, Label)
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
- Źródło:
- ILGenerator.cs
Umieszcza określoną instrukcję na strumieniu Microsoft języka pośredniego (MSIL) i pozostawia miejsce, aby dołączyć etykietę po zakończeniu poprawek.
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)
Parametry
- opcode
- OpCode
Instrukcja MSIL, która ma być emitowana do strumienia.
- label
- Label
Etykieta, do której ma być rozgałęziona z tej lokalizacji.
Przykłady
Poniższy przykład kodu ilustruje tworzenie metody dynamicznej z tabelą skoków. Tabela skoków jest tworzona przy użyciu tablicy 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
Uwagi
Wartości instrukcji są definiowane w wyliczeniu OpCodes .
Etykiety są tworzone przy użyciu elementu DefineLabel, a ich lokalizacja w strumieniu jest stała przy użyciu polecenia MarkLabel. Jeśli jest używana instrukcja jednobajtowa, etykieta może reprezentować skok co najwyżej 127 bajtów wzdłuż strumienia.
opcode musi reprezentować instrukcję gałęzi. Ponieważ gałęzie są instrukcjami względnymi, label zostaną zastąpione poprawnym przesunięciem do gałęzi podczas procesu naprawiania.