ILGenerator.Emit Methode
Definition
Wichtig
Einige Informationen beziehen sich auf Vorabversionen, die vor dem Release ggf. grundlegend überarbeitet werden. Microsoft übernimmt hinsichtlich der hier bereitgestellten Informationen keine Gewährleistungen, seien sie ausdrücklich oder konkludent.
Fügt eine Anweisung in den MSIL-Stream (Microsoft Intermediate Language) für den JIT-Compiler (Just-In-Time) ein.
Überlädt
Emit(OpCode, LocalBuilder) |
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Index der angegebenen lokalen Variable. |
Emit(OpCode, Type) |
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Metadatentoken für den angegebenen Typ. |
Emit(OpCode, String) |
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Metadatentoken für die angegebene Zeichenfolge. |
Emit(OpCode, Single) |
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, SByte) |
Fügt die angegebene Anweisung und das Zeichenargument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, MethodInfo) |
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Metadatentoken für die angegebene Methode. |
Emit(OpCode, SignatureHelper) |
Fügt die angegebene Anweisung und ein Signaturtoken in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, Label[]) |
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein und lässt für den Fall von Korrekturen Platz zum Einfügen einer Sprungmarke. |
Emit(OpCode, FieldInfo) |
Fügt die angegebene Anweisung und das Metadatentoken für das angegebene Feld in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, ConstructorInfo) |
Fügt die angegebene Anweisung und das Metadatentoken für den angegebenen Konstruktor in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, Int64) |
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, Int32) |
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, Int16) |
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, Double) |
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode, Byte) |
Fügt die angegebene Anweisung und das Zeichenargument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein. |
Emit(OpCode) |
Fügt die angegebene Anweisung in den Anweisungsstream ein. |
Emit(OpCode, Label) |
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein und lässt für den Fall von Korrekturen Platz zum Einfügen einer Sprungmarke. |
Emit(OpCode, LocalBuilder)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Index der angegebenen lokalen Variable.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
Public Overridable Sub Emit (opcode As OpCode, local As LocalBuilder)
Public MustOverride Sub Emit (opcode As OpCode, local As LocalBuilder)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- local
- LocalBuilder
Eine lokale Variable.
Ausnahmen
Die übergeordnete Methode des local
-Parameters stimmt nicht mit der Methode überein, die diesem ILGenerator zugeordnet ist.
local
ist null
.
opcode
ist eine Einzelbyteanweisung, und local
stellt eine lokale Variable mit einem Index dar, der größer als Byte.MaxValue
ist.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, Type)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Metadatentoken für den angegebenen Typ.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, Type cls);
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
override this.Emit : System.Reflection.Emit.OpCode * Type -> unit
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
Public Overridable Sub Emit (opcode As OpCode, cls As Type)
Public MustOverride Sub Emit (opcode As OpCode, cls As Type)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung.
- cls
- Type
Ein Type
.
Ausnahmen
cls
ist null
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert. Der Speicherort von cls
wird aufgezeichnet, sodass das Token bei Bedarf gepatcht werden kann, wenn das Modul in einer portablen ausführbaren Datei (PE) beibehalten wird.
Gilt für:
Emit(OpCode, String)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Metadatentoken für die angegebene Zeichenfolge.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, string str);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, string str);
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
override this.Emit : System.Reflection.Emit.OpCode * string -> unit
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
Public Overridable Sub Emit (opcode As OpCode, str As String)
Public MustOverride Sub Emit (opcode As OpCode, str As String)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- str
- String
Der auszugebende String
.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert. Der Speicherort von str
wird für zukünftige Korrekturen aufgezeichnet, wenn das Modul in einer portablen ausführbaren Datei (PE) beibehalten wird.
Gilt für:
Emit(OpCode, Single)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, float arg);
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
override this.Emit : System.Reflection.Emit.OpCode * single -> unit
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Single)
Public MustOverride Sub Emit (opcode As OpCode, arg As Single)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, SByte)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Wichtig
Diese API ist nicht CLS-kompatibel.
Fügt die angegebene Anweisung und das Zeichenargument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung.
- arg
- SByte
Das unmittelbar hinter der Anweisung in den Stream eingefügte Zeichenargument.
- Attribute
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, MethodInfo)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein, gefolgt vom Metadatentoken für die angegebene Methode.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
Public Overridable Sub Emit (opcode As OpCode, meth As MethodInfo)
Public MustOverride Sub Emit (opcode As OpCode, meth As MethodInfo)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- meth
- MethodInfo
Eine MethodInfo
, die eine Methode darstellt.
Ausnahmen
meth
ist null
.
meth
ist eine generische Methode, für die die IsGenericMethodDefinition-Eigenschaft false
ist.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Der Speicherort von meth
wird aufgezeichnet, sodass der Anweisungsstream bei Bedarf gepatcht werden kann, wenn das Modul in einer portablen ausführbaren Datei (PE) beibehalten wird.
Wenn meth
eine generische Methode darstellt, muss es sich um eine generische Methodendefinition sein. Das heißt, die MethodInfo.IsGenericMethodDefinition-Eigenschaft muss sein true
.
Gilt für:
Emit(OpCode, SignatureHelper)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und ein Signaturtoken in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
Public Overridable Sub Emit (opcode As OpCode, signature As SignatureHelper)
Public MustOverride Sub Emit (opcode As OpCode, signature As SignatureHelper)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- signature
- SignatureHelper
Ein Helper zum Erstellen eines Signaturtokens.
Ausnahmen
signature
ist null
.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, Label[])
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein und lässt für den Fall von Korrekturen Platz zum Einfügen einer Sprungmarke.
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, cli::array <System::Reflection::Emit::Label> ^ labels);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
Public Overridable Sub Emit (opcode As OpCode, labels As Label())
Public MustOverride Sub Emit (opcode As OpCode, labels As Label())
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- labels
- Label[]
Das Array von Sprungmarkenobjekten, zu denen von dieser Position aus verzweigt werden soll. Es werden alle Sprungmarken verwendet.
Ausnahmen
con
ist null
. Diese Ausnahme ist in der .NET Framework 4 neu.
Beispiele
Im folgenden Codebeispiel wird die Erstellung einer dynamischen Methode mit einer Sprungtabelle veranschaulicht. Die Sprungtabelle wird mithilfe eines Arrays von Labelerstellt.
using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
Type^ BuildMyType()
{
AppDomain^ myDomain = Thread::GetDomain();
AssemblyName^ myAsmName = gcnew AssemblyName;
myAsmName->Name = "MyDynamicAssembly";
AssemblyBuilder^ myAsmBuilder = myDomain->DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess::Run );
ModuleBuilder^ myModBuilder = myAsmBuilder->DefineDynamicModule( "MyJumpTableDemo" );
TypeBuilder^ myTypeBuilder = myModBuilder->DefineType( "JumpTableDemo", TypeAttributes::Public );
array<Type^>^temp0 = {int::typeid};
MethodBuilder^ myMthdBuilder = myTypeBuilder->DefineMethod( "SwitchMe", static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static), String::typeid, temp0 );
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.
array<Label>^jumpTable = gcnew array<Label>(5);
jumpTable[ 0 ] = myIL->DefineLabel();
jumpTable[ 1 ] = myIL->DefineLabel();
jumpTable[ 2 ] = myIL->DefineLabel();
jumpTable[ 3 ] = myIL->DefineLabel();
jumpTable[ 4 ] = 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();
}
int 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, gcnew array<Object^>(0) );
array<Object^>^temp1 = {theValue};
Console::WriteLine( "Yes, there {0} today!", myType->InvokeMember( "SwitchMe", BindingFlags::InvokeMethod, nullptr, myInstance, temp1 ) );
}
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
Hinweise
Gibt eine Switchtabelle aus.
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Bezeichnungen werden mit DefineLabel erstellt, und ihre Position im Stream wird mithilfe MarkLabelvon festgelegt. Wenn eine Ein-Byte-Anweisung verwendet wird, kann die Bezeichnung einen Sprung von maximal 127 Bytes entlang des Datenstroms darstellen.
opcode
muss eine Branchanweisung darstellen. Da Branches relative Anweisungen sind, label
werden sie während des Fixupvorgangs durch den richtigen Offset in Branch ersetzt.
Gilt für:
Emit(OpCode, FieldInfo)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das Metadatentoken für das angegebene Feld in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
Public Overridable Sub Emit (opcode As OpCode, field As FieldInfo)
Public MustOverride Sub Emit (opcode As OpCode, field As FieldInfo)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- field
- FieldInfo
Eine FieldInfo
, die ein Feld darstellt.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert. Der Speicherort von field
wird aufgezeichnet, sodass der Anweisungsstream bei Bedarf gepatcht werden kann, wenn das Modul in einer portablen ausführbaren Datei (PE) beibehalten wird.
Gilt für:
Emit(OpCode, ConstructorInfo)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das Metadatentoken für den angegebenen Konstruktor in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract 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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
abstract member 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 Overridable Sub Emit (opcode As OpCode, con As ConstructorInfo)
Public MustOverride Sub Emit (opcode As OpCode, con As ConstructorInfo)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- con
- ConstructorInfo
Eine ConstructorInfo
, die einen Konstruktor darstellt.
- Attribute
Ausnahmen
con
ist null
Diese Ausnahme ist in der .NET Framework 4 neu.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Der Speicherort von con
wird aufgezeichnet, sodass der Anweisungsstream bei Bedarf gepatcht werden kann, wenn das Modul in einer portablen ausführbaren Datei (PE) beibehalten wird.
Gilt für:
Emit(OpCode, Int64)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, long arg);
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int64 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Long)
Public MustOverride Sub Emit (opcode As OpCode, arg As Long)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung.
- arg
- Int64
Das unmittelbar hinter der Anweisung in den Stream eingefügte numerische Argument.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, Int32)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, int arg);
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
override this.Emit : System.Reflection.Emit.OpCode * int -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Integer)
Public MustOverride Sub Emit (opcode As OpCode, arg As Integer)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung.
- arg
- Int32
Das unmittelbar hinter der Anweisung in den Stream eingefügte numerische Argument.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, Int16)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, short arg);
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int16 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Short)
Public MustOverride Sub Emit (opcode As OpCode, arg As Short)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- arg
- Int16
Das unmittelbar hinter der Anweisung in den Stream eingefügte Int
-Argument.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, Double)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das numerische Argument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, double arg);
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
override this.Emit : System.Reflection.Emit.OpCode * double -> unit
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Double)
Public MustOverride Sub Emit (opcode As OpCode, arg As Double)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung. In der OpCodes
-Enumeration definiert.
- arg
- Double
Das unmittelbar hinter der Anweisung in den Stream eingefügte numerische Argument.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode, Byte)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung und das Zeichenargument in den MSIL-Anweisungsstream (Microsoft Intermediate Language) ein.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, byte arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, byte arg);
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
override this.Emit : System.Reflection.Emit.OpCode * byte -> unit
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Byte)
Public MustOverride Sub Emit (opcode As OpCode, arg As Byte)
Parameter
- opcode
- OpCode
Die an den Stream auszugebende MSIL-Anweisung.
- arg
- Byte
Das unmittelbar hinter der Anweisung in den Stream eingefügte Zeichenargument.
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Gilt für:
Emit(OpCode)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den Anweisungsstream ein.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode);
abstract member Emit : System.Reflection.Emit.OpCode -> unit
override this.Emit : System.Reflection.Emit.OpCode -> unit
abstract member Emit : System.Reflection.Emit.OpCode -> unit
Public Overridable Sub Emit (opcode As OpCode)
Public MustOverride Sub Emit (opcode As OpCode)
Parameter
- opcode
- OpCode
Die in den Stream einzufügende MSIL-Anweisung (Microsoft Intermediate Language).
Beispiele
Im folgenden Codebeispiel wird die Verwendung von Emit
veranschaulicht, um eine MSIL-Ausgabe über eine instance von ILGeneratorzu generieren.
using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
Type^ BuildMyType()
{
AppDomain^ myDomain = Thread::GetDomain();
AssemblyName^ myAsmName = gcnew AssemblyName;
myAsmName->Name = "MyDynamicAssembly";
AssemblyBuilder^ myAsmBuilder = myDomain->DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess::Run );
ModuleBuilder^ myModBuilder = myAsmBuilder->DefineDynamicModule( "MyJumpTableDemo" );
TypeBuilder^ myTypeBuilder = myModBuilder->DefineType( "JumpTableDemo", TypeAttributes::Public );
array<Type^>^temp0 = {int::typeid};
MethodBuilder^ myMthdBuilder = myTypeBuilder->DefineMethod( "SwitchMe", static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static), String::typeid, temp0 );
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.
array<Label>^jumpTable = gcnew array<Label>(5);
jumpTable[ 0 ] = myIL->DefineLabel();
jumpTable[ 1 ] = myIL->DefineLabel();
jumpTable[ 2 ] = myIL->DefineLabel();
jumpTable[ 3 ] = myIL->DefineLabel();
jumpTable[ 4 ] = 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();
}
int 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, gcnew array<Object^>(0) );
array<Object^>^temp1 = {theValue};
Console::WriteLine( "Yes, there {0} today!", myType->InvokeMember( "SwitchMe", BindingFlags::InvokeMethod, nullptr, myInstance, temp1 ) );
}
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
Hinweise
Wenn der opcode
Parameter ein Argument erfordert, muss der Aufrufer sicherstellen, dass die Argumentlänge mit der Länge des deklarierten Parameters übereinstimmt. Andernfalls sind die Ergebnisse unvorhersehbar. Wenn die Emit-Anweisung beispielsweise einen 2-Byte-Operanden erfordert und der Aufrufer einen 4-Byte-Operanden bereitstellt, gibt die Runtime zwei zusätzliche Bytes an den Anweisungsstream aus. Diese zusätzlichen Bytes sind Nop Anweisungen.
Die Befehlswerte werden in OpCodesdefiniert.
Gilt für:
Emit(OpCode, Label)
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
- Quelle:
- ILGenerator.cs
Fügt die angegebene Anweisung in den MSIL-Stream (Microsoft Intermediate Language) ein und lässt für den Fall von Korrekturen Platz zum Einfügen einer Sprungmarke.
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);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
Public Overridable Sub Emit (opcode As OpCode, label As Label)
Public MustOverride Sub Emit (opcode As OpCode, label As Label)
Parameter
- opcode
- OpCode
Die MSIL-Anweisung, die in den Datenstrom ausgegeben werden soll.
- label
- Label
Die Sprungmarke, zu der von dieser Position aus verzweigt werden soll.
Beispiele
Im folgenden Codebeispiel wird die Erstellung einer dynamischen Methode mit einer Sprungtabelle veranschaulicht. Die Sprungtabelle wird mithilfe eines Arrays von Labelerstellt.
using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
Type^ BuildMyType()
{
AppDomain^ myDomain = Thread::GetDomain();
AssemblyName^ myAsmName = gcnew AssemblyName;
myAsmName->Name = "MyDynamicAssembly";
AssemblyBuilder^ myAsmBuilder = myDomain->DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess::Run );
ModuleBuilder^ myModBuilder = myAsmBuilder->DefineDynamicModule( "MyJumpTableDemo" );
TypeBuilder^ myTypeBuilder = myModBuilder->DefineType( "JumpTableDemo", TypeAttributes::Public );
array<Type^>^temp0 = {int::typeid};
MethodBuilder^ myMthdBuilder = myTypeBuilder->DefineMethod( "SwitchMe", static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static), String::typeid, temp0 );
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.
array<Label>^jumpTable = gcnew array<Label>(5);
jumpTable[ 0 ] = myIL->DefineLabel();
jumpTable[ 1 ] = myIL->DefineLabel();
jumpTable[ 2 ] = myIL->DefineLabel();
jumpTable[ 3 ] = myIL->DefineLabel();
jumpTable[ 4 ] = 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();
}
int 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, gcnew array<Object^>(0) );
array<Object^>^temp1 = {theValue};
Console::WriteLine( "Yes, there {0} today!", myType->InvokeMember( "SwitchMe", BindingFlags::InvokeMethod, nullptr, myInstance, temp1 ) );
}
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
Hinweise
Die Befehlswerte werden in der OpCodes
Enumeration definiert.
Bezeichnungen werden mit DefineLabelerstellt, und ihre Position im Stream wird mithilfe MarkLabelvon festgelegt. Wenn eine Ein-Byte-Anweisung verwendet wird, kann die Bezeichnung einen Sprung von maximal 127 Bytes entlang des Datenstroms darstellen.
opcode
muss eine Branchanweisung darstellen. Da Branches relative Anweisungen sind, label
werden sie während des Fixupvorgangs durch den richtigen Offset in Branch ersetzt.