ILGenerator.Emit ILGenerator.Emit ILGenerator.Emit Method

定义

将指令放到实时 (JIT) 编译器的 Microsoft 中间语言 (MSIL) 流上。Puts an instruction onto the Microsoft Intermediate Language (MSIL) stream for the just-in-time (JIT) compiler.

重载

Emit(OpCode, Type) Emit(OpCode, Type) Emit(OpCode, Type)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定类型的元数据令牌。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the metadata token for the given type.

Emit(OpCode, String) Emit(OpCode, String) Emit(OpCode, String)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定字符串的元数据令牌。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the metadata token for the given string.

Emit(OpCode, Single) Emit(OpCode, Single) Emit(OpCode, Single)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, SByte) Emit(OpCode, SByte) Emit(OpCode, SByte)

将指定的指令和字符参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and character argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, FieldInfo) Emit(OpCode, FieldInfo) Emit(OpCode, FieldInfo)

将指定字段的指定指令和元数据令牌放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and metadata token for the specified field onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, SignatureHelper) Emit(OpCode, SignatureHelper) Emit(OpCode, SignatureHelper)

将指定的指令和签名令牌放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and a signature token onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, LocalBuilder) Emit(OpCode, LocalBuilder) Emit(OpCode, LocalBuilder)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定局部变量的索引。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the index of the given local variable.

Emit(OpCode, Label[]) Emit(OpCode, Label[]) Emit(OpCode, Label[])

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,并留出在完成修正时加上标签所需的空白。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.

Emit(OpCode, MethodInfo) Emit(OpCode, MethodInfo) Emit(OpCode, MethodInfo)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定方法的元数据令牌。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the metadata token for the given method.

Emit(OpCode, ConstructorInfo) Emit(OpCode, ConstructorInfo) Emit(OpCode, ConstructorInfo)

将指定构造函数的指定指令和元数据令牌放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and metadata token for the specified constructor onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, Int64) Emit(OpCode, Int64) Emit(OpCode, Int64)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, Int32) Emit(OpCode, Int32) Emit(OpCode, Int32)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, Int16) Emit(OpCode, Int16) Emit(OpCode, Int16)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, Double) Emit(OpCode, Double) Emit(OpCode, Double)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode, Byte) Emit(OpCode, Byte) Emit(OpCode, Byte)

将指定的指令和字符参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and character argument onto the Microsoft intermediate language (MSIL) stream of instructions.

Emit(OpCode) Emit(OpCode) Emit(OpCode)

将指定的指令放到指令流上。Puts the specified instruction onto the stream of instructions.

Emit(OpCode, Label) Emit(OpCode, Label) Emit(OpCode, Label)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,并留出在完成修正时加上标签所需的空白。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.

Emit(OpCode, Type) Emit(OpCode, Type) Emit(OpCode, Type)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定类型的元数据令牌。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the metadata token for the given type.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * Type -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream.

cls
Type Type Type

TypeA Type.

异常

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration. 记录的位置cls , 以便在将模块保存到可移植可执行 (PE) 文件中时, 可以对令牌进行修补。The location of cls is recorded so that the token can be patched if necessary when persisting the module to a portable executable (PE) file.

Emit(OpCode, String) Emit(OpCode, String) Emit(OpCode, String)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定字符串的元数据令牌。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the metadata token for the given string.

public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public virtual 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

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

str
String String String

要发出的 StringThe String to be emitted.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration. 如果模块保存str到可移植可执行 (PE) 文件中, 则会记录的位置以供将来修正。The location of str is recorded for future fixups if the module is persisted to a portable executable (PE) file.

Emit(OpCode, Single) Emit(OpCode, Single) Emit(OpCode, Single)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * single -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream.

arg
Single Single Single

紧接着该指令推到流中的 Single 参数。The Single argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, SByte) Emit(OpCode, SByte) Emit(OpCode, SByte)

重要

此 API 不符合 CLS。

将指定的指令和字符参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and character argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 void Emit(System::Reflection::Emit::OpCode opcode, System::SByte arg);
[System.CLSCompliant(false)]
public void Emit (System.Reflection.Emit.OpCode opcode, sbyte arg);
member this.Emit : System.Reflection.Emit.OpCode * sbyte -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream.

arg
SByte SByte SByte

紧接着该指令推到流中的字符参数。The character argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, FieldInfo) Emit(OpCode, FieldInfo) Emit(OpCode, FieldInfo)

将指定字段的指定指令和元数据令牌放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and metadata token for the specified field onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

field
FieldInfo FieldInfo FieldInfo

表示字段的 FieldInfoA FieldInfo representing a field.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration. 记录的位置field , 以便在将模块保存到可移植可执行 (PE) 文件中时, 可以在必要时对指令流进行修补。The location of field is recorded so that the instruction stream can be patched if necessary when persisting the module to a portable executable (PE) file.

Emit(OpCode, SignatureHelper) Emit(OpCode, SignatureHelper) Emit(OpCode, SignatureHelper)

将指定的指令和签名令牌放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and a signature token onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

signature
SignatureHelper SignatureHelper SignatureHelper

用于构造签名令牌的帮助程序。A helper for constructing a signature token.

异常

signaturenullsignature is null.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, LocalBuilder) Emit(OpCode, LocalBuilder) Emit(OpCode, LocalBuilder)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定局部变量的索引。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the index of the given local variable.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

local
LocalBuilder LocalBuilder LocalBuilder

局部变量。A local variable.

异常

local 参数的父方法与此 ILGenerator 关联的方法不匹配。The parent method of the local parameter does not match the method associated with this ILGenerator.

opcode 是单字节指令,并且 local 表示索引大于 Byte.MaxValue 的局部变量。opcode is a single-byte instruction, and local represents a local variable with an index greater than Byte.MaxValue.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, Label[]) Emit(OpCode, Label[]) Emit(OpCode, Label[])

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,并留出在完成修正时加上标签所需的空白。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.

public:
 virtual 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);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

labels
Label[]

从此位置分支到的标签对象的数组。The array of label objects to which to branch from this location. 将使用所有标签。All of the labels will be used.

异常

connullcon is null. 此异常是 .NET Framework 4.NET Framework 4 中新出现的。This exception is new in the .NET Framework 4.NET Framework 4.

示例

下面的代码示例演示如何使用跳转表创建动态方法。The code sample below illustrates the creation of a dynamic method with a jump table. 跳转表是使用数组Label生成的。The jump table is built using an array of Label.

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
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 'Main

End Class 'DynamicJumpTableDemo

注解

发出切换表。Emits a switch table.

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

标签是使用DefineLabel创建的, 其在流中的位置是使用MarkLabel固定的。Labels are created using DefineLabel and their location within the stream is fixed by using MarkLabel. 如果使用单字节指令, 则标签最多可以表示流中最多127个字节。If a single-byte instruction is used, the label can represent a jump of at most 127 bytes along the stream. opcode必须表示分支指令。opcode must represent a branch instruction. 由于分支是相对说明, label因此在修复过程中将替换为分支的正确偏移量。Because branches are relative instructions, label will be replaced with the correct offset to branch during the fixup process.

Emit(OpCode, MethodInfo) Emit(OpCode, MethodInfo) Emit(OpCode, MethodInfo)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,后跟给定方法的元数据令牌。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream followed by the metadata token for the given method.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

meth
MethodInfo MethodInfo MethodInfo

表示方法的 MethodInfoA MethodInfo representing a method.

异常

meth 为泛型方法,其 IsGenericMethodDefinition 属性为 falsemeth is a generic method for which the IsGenericMethodDefinition property is false.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

记录的位置meth , 以便在将模块保存到可移植可执行 (PE) 文件中时, 可以在必要时对指令流进行修补。The location of meth is recorded so that the instruction stream can be patched if necessary when persisting the module to a portable executable (PE) file.

如果meth表示泛型方法, 则它必须是泛型方法定义。If meth represents a generic method, it must be a generic method definition. 也就是说, 其IsGenericMethodDefinition属性必须是trueThat is, its MethodInfo.IsGenericMethodDefinition property must be true.

Emit(OpCode, ConstructorInfo) Emit(OpCode, ConstructorInfo) Emit(OpCode, ConstructorInfo)

将指定构造函数的指定指令和元数据令牌放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and metadata token for the specified constructor onto the Microsoft intermediate language (MSIL) stream of instructions.

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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

con
ConstructorInfo ConstructorInfo ConstructorInfo

表示构造函数的 ConstructorInfoA ConstructorInfo representing a constructor.

异常

connullcon is null. 此异常是 .NET Framework 4.NET Framework 4 中新出现的。This exception is new in the .NET Framework 4.NET Framework 4.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

记录的位置con , 以便在将模块保存到可移植可执行 (PE) 文件中时, 可以在必要时对指令流进行修补。The location of con is recorded so that the instruction stream can be patched if necessary when persisting the module to a portable executable (PE) file.

Emit(OpCode, Int64) Emit(OpCode, Int64) Emit(OpCode, Int64)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * int64 -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream.

arg
Int64 Int64 Int64

紧接着该指令推到流中的数字参数。The numerical argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, Int32) Emit(OpCode, Int32) Emit(OpCode, Int32)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * int -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream.

arg
Int32 Int32 Int32

紧接着该指令推到流中的数字参数。The numerical argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, Int16) Emit(OpCode, Int16) Emit(OpCode, Int16)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * int16 -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

arg
Int16 Int16 Int16

紧接着该指令推到流中的 Int 参数。The Int argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, Double) Emit(OpCode, Double) Emit(OpCode, Double)

将指定的指令和数值参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and numerical argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * double -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream. OpCodes 枚举中定义。Defined in the OpCodes enumeration.

arg
Double Double Double

紧接着该指令推到流中的数字参数。The numerical argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode, Byte) Emit(OpCode, Byte) Emit(OpCode, Byte)

将指定的指令和字符参数放到 Microsoft 中间语言 (MSIL) 指令流上。Puts the specified instruction and character argument onto the Microsoft intermediate language (MSIL) stream of instructions.

public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public virtual 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

参数

opcode
OpCode OpCode OpCode

要放到流上的 MSIL 指令。The MSIL instruction to be put onto the stream.

arg
Byte Byte Byte

紧接着该指令推到流中的字符参数。The character argument pushed onto the stream immediately after the instruction.

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

Emit(OpCode) Emit(OpCode) Emit(OpCode)

将指定的指令放到指令流上。Puts the specified instruction onto the stream of instructions.

public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode);
public virtual void Emit (System.Reflection.Emit.OpCode opcode);
abstract member Emit : System.Reflection.Emit.OpCode -> unit
override this.Emit : System.Reflection.Emit.OpCode -> unit

参数

opcode
OpCode OpCode OpCode

要放到流上的 Microsoft 中间语言 (MSIL) 指令。The Microsoft Intermediate Language (MSIL) instruction to be put onto the stream.

示例

下面的代码示例演示Emit如何使用通过ILGenerator实例生成 MSIL 输出。The code sample below demonstrates the use of Emit to generate MSIL output via an instance of ILGenerator.

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
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 'Main

End Class 'DynamicJumpTableDemo

注解

opcode如果参数需要参数, 则调用方必须确保参数长度与已声明参数的长度匹配。If the opcode parameter requires an argument, the caller must ensure that the argument length matches the length of the declared parameter. 否则, 结果将是不可预知的。Otherwise, results will be unpredictable. 例如, 如果发出指令需要2字节操作数, 并且调用方提供4字节操作数, 则运行时将向指令流发出两个额外的字节。For example, if the Emit instruction requires a 2-byte operand and the caller supplies a 4-byte operand, the runtime will emit two additional bytes to the instruction stream. 这些额外的字节将Nop是说明。These extra bytes will be Nop instructions.

OpCodes定义了说明值。The instruction values are defined in OpCodes.

Emit(OpCode, Label) Emit(OpCode, Label) Emit(OpCode, Label)

将指定的指令放到 Microsoft 中间语言 (MSIL) 流上,并留出在完成修正时加上标签所需的空白。Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.

public:
 virtual 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
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit

参数

opcode
OpCode OpCode OpCode

要发出到流的 MSIL 指令。The MSIL instruction to be emitted onto the stream.

label
Label Label Label

从此位置分支到的标签。The label to which to branch from this location.

示例

下面的代码示例演示如何使用跳转表创建动态方法。The code sample below illustrates the creation of a dynamic method with a jump table. 跳转表是使用数组Label生成的。The jump table is built using an array of Label.

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
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 'Main

End Class 'DynamicJumpTableDemo

注解

说明值是在OpCodes枚举中定义的。The instruction values are defined in the OpCodes enumeration.

标签是使用DefineLabel创建的, 其在流中的位置是使用MarkLabel固定的。Labels are created using DefineLabel, and their location within the stream is fixed by using MarkLabel. 如果使用单字节指令, 则标签最多可以表示流中最多127个字节。If a single-byte instruction is used, the label can represent a jump of at most 127 bytes along the stream. opcode必须表示分支指令。opcode must represent a branch instruction. 由于分支是相对说明, label因此在修复过程中将替换为分支的正确偏移量。Because branches are relative instructions, label will be replaced with the correct offset to branch during the fixup process.

适用于