Partilhar via


ILGenerator.Emit Método

Definição

Coloca uma instrução no fluxo Microsoft LINGUAGEm Intermediária (MSIL) para o compilador JIT (just-in-time).

Sobrecargas

Nome Description
Emit(OpCode, LocalBuilder)

Coloca a instrução especificada no fluxo de linguagem Microsoft intermediária (MSIL) seguido pelo índice da variável local fornecida.

Emit(OpCode, Type)

Coloca a instrução especificada no fluxo msil (linguagem intermediária) Microsoft seguido pelo token de metadados para o tipo fornecido.

Emit(OpCode, String)

Coloca a instrução especificada no fluxo msil (linguagem intermediária) Microsoft seguida pelo token de metadados para a cadeia de caracteres fornecida.

Emit(OpCode, Single)

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, SByte)

Coloca a instrução especificada e o argumento de caractere no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, FieldInfo)

Coloca o token de instrução e metadados especificados para o campo especificado no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, SignatureHelper)

Coloca a instrução especificada e um token de assinatura no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, Label[])

Coloca a instrução especificada no fluxo de Microsoft linguagem intermediária (MSIL) e deixa espaço para incluir um rótulo quando as correções forem feitas.

Emit(OpCode, MethodInfo)

Coloca a instrução especificada no fluxo msil (linguagem intermediária) Microsoft seguido pelo token de metadados para o método fornecido.

Emit(OpCode, ConstructorInfo)

Coloca a instrução especificada e o token de metadados do construtor especificado no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, Int64)

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, Int32)

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, Int16)

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, Double)

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode, Byte)

Coloca a instrução especificada e o argumento de caractere no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

Emit(OpCode)

Coloca a instrução especificada no fluxo de instruções.

Emit(OpCode, Label)

Coloca a instrução especificada no fluxo de Microsoft linguagem intermediária (MSIL) e deixa espaço para incluir um rótulo quando as correções forem feitas.

Emit(OpCode, LocalBuilder)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo de linguagem Microsoft intermediária (MSIL) seguido pelo índice da variável local fornecida.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::LocalBuilder ^ local);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::LocalBuilder ^ local);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
Public MustOverride Sub Emit (opcode As OpCode, local As LocalBuilder)
Public Overridable Sub Emit (opcode As OpCode, local As LocalBuilder)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

local
LocalBuilder

Uma variável local.

Exceções

O método pai do local parâmetro não corresponde ao método associado a este ILGenerator.

local é null.

opcode é uma instrução de byte único e local representa uma variável local com um índice maior que Byte.MaxValue.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, Type)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo msil (linguagem intermediária) Microsoft seguido pelo token de metadados para o tipo fornecido.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, Type ^ cls);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, Type ^ cls);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, Type cls);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, Type cls);
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
override this.Emit : System.Reflection.Emit.OpCode * Type -> unit
Public MustOverride Sub Emit (opcode As OpCode, cls As Type)
Public Overridable Sub Emit (opcode As OpCode, cls As Type)

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo.

cls
Type

Um Type.

Exceções

cls é null.

Comentários

Os valores de instrução são definidos na OpCodes enumeração. O local do cls qual é registrado para que o token possa ser corrigido, se necessário, ao persistir o módulo em um arquivo PE (executável portátil).

Aplica-se a

Emit(OpCode, String)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo msil (linguagem intermediária) Microsoft seguida pelo token de metadados para a cadeia de caracteres fornecida.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, string str);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, string str);
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
override this.Emit : System.Reflection.Emit.OpCode * string -> unit
Public MustOverride Sub Emit (opcode As OpCode, str As String)
Public Overridable Sub Emit (opcode As OpCode, str As String)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

str
String

O String a ser emitido.

Comentários

Os valores de instrução são definidos na OpCodes enumeração. O local do str qual será registrado para correções futuras se o módulo for mantido em um arquivo PE (executável portátil).

Aplica-se a

Emit(OpCode, Single)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, float arg);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, float arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, float arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, float arg);
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
override this.Emit : System.Reflection.Emit.OpCode * single -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Single)
Public Overridable Sub Emit (opcode As OpCode, arg As Single)

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo.

arg
Single

O Single argumento foi enviado para o fluxo imediatamente após a instrução.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, SByte)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Importante

Esta API não está em conformidade com CLS.

Coloca a instrução especificada e o argumento de caractere no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

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

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo.

arg
SByte

O argumento de caractere enviado para o fluxo imediatamente após a instrução.

Atributos

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, FieldInfo)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca o token de instrução e metadados especificados para o campo especificado no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::FieldInfo ^ field);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::FieldInfo ^ field);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
Public MustOverride Sub Emit (opcode As OpCode, field As FieldInfo)
Public Overridable Sub Emit (opcode As OpCode, field As FieldInfo)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

field
FieldInfo

Um FieldInfo campo que representa.

Comentários

Os valores de instrução são definidos na OpCodes enumeração. O local do qual é registrado para que o fluxo de field instruções possa ser corrigido, se necessário, ao persistir o módulo em um arquivo PE (executável portátil).

Aplica-se a

Emit(OpCode, SignatureHelper)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e um token de assinatura no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::SignatureHelper ^ signature);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::SignatureHelper ^ signature);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
Public MustOverride Sub Emit (opcode As OpCode, signature As SignatureHelper)
Public Overridable Sub Emit (opcode As OpCode, signature As SignatureHelper)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

signature
SignatureHelper

Um auxiliar para construir um token de assinatura.

Exceções

signature é null.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, Label[])

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo de Microsoft linguagem intermediária (MSIL) e deixa espaço para incluir um rótulo quando as correções forem feitas.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, cli::array <System::Reflection::Emit::Label> ^ labels);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, cli::array <System::Reflection::Emit::Label> ^ labels);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
Public MustOverride Sub Emit (opcode As OpCode, labels As Label())
Public Overridable Sub Emit (opcode As OpCode, labels As Label())

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

labels
Label[]

A matriz de objetos de rótulo para os quais ramificar a partir desse local. Todos os rótulos serão usados.

Exemplos

O exemplo de código abaixo ilustra a criação de um método dinâmico com uma tabela de salto. A tabela de salto é criada usando uma matriz de Label.

using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;

class DynamicJumpTableDemo
{
   public static Type BuildMyType()
   {
    AppDomain myDomain = Thread.GetDomain();
    AssemblyName myAsmName = new AssemblyName();
    myAsmName.Name = "MyDynamicAssembly";

    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                        myAsmName,
                        AssemblyBuilderAccess.Run);
    ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
                        "MyJumpTableDemo");

    TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
                            TypeAttributes.Public);
    MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
                             MethodAttributes.Public |
                             MethodAttributes.Static,
                                             typeof(string),
                                             new Type[] {typeof(int)});

    ILGenerator myIL = myMthdBuilder.GetILGenerator();

    Label defaultCase = myIL.DefineLabel();	
    Label endOfMethod = myIL.DefineLabel();	

    // We are initializing our jump table. Note that the labels
    // will be placed later using the MarkLabel method.

    Label[] jumpTable = new Label[] { myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel() };

    // arg0, the number we passed, is pushed onto the stack.
    // In this case, due to the design of the code sample,
    // the value pushed onto the stack happens to match the
    // index of the label (in IL terms, the index of the offset
    // in the jump table). If this is not the case, such as
    // when switching based on non-integer values, rules for the correspondence
    // between the possible case values and each index of the offsets
    // must be established outside of the ILGenerator.Emit calls,
    // much as a compiler would.

    myIL.Emit(OpCodes.Ldarg_0);
    myIL.Emit(OpCodes.Switch, jumpTable);
    
    // Branch on default case
    myIL.Emit(OpCodes.Br_S, defaultCase);

    // Case arg0 = 0
    myIL.MarkLabel(jumpTable[0]);
    myIL.Emit(OpCodes.Ldstr, "are no bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 1
    myIL.MarkLabel(jumpTable[1]);
    myIL.Emit(OpCodes.Ldstr, "is one banana");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 2
    myIL.MarkLabel(jumpTable[2]);
    myIL.Emit(OpCodes.Ldstr, "are two bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 3
    myIL.MarkLabel(jumpTable[3]);
    myIL.Emit(OpCodes.Ldstr, "are three bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 4
    myIL.MarkLabel(jumpTable[4]);
    myIL.Emit(OpCodes.Ldstr, "are four bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Default case
    myIL.MarkLabel(defaultCase);
    myIL.Emit(OpCodes.Ldstr, "are many bananas");

    myIL.MarkLabel(endOfMethod);
    myIL.Emit(OpCodes.Ret);
    
    return myTypeBuilder.CreateType();
   }

   public static void Main()
   {
    Type myType = BuildMyType();
    
    Console.Write("Enter an integer between 0 and 5: ");
    int theValue = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("---");
    Object myInstance = Activator.CreateInstance(myType, new object[0]);	
    Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
                               BindingFlags.InvokeMethod,
                               null,
                               myInstance,
                               new object[] {theValue}));
   }
}

Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit

 _

Class DynamicJumpTableDemo
   
   Public Shared Function BuildMyType() As Type

      Dim myDomain As AppDomain = Thread.GetDomain()
      Dim myAsmName As New AssemblyName()
      myAsmName.Name = "MyDynamicAssembly"
      
      Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
                            AssemblyBuilderAccess.Run)
      Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
      
      Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
                                 TypeAttributes.Public)
      Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
                        MethodAttributes.Public Or MethodAttributes.Static, _
                        GetType(String), New Type() {GetType(Integer)})
      
      Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
      
      Dim defaultCase As Label = myIL.DefineLabel()
      Dim endOfMethod As Label = myIL.DefineLabel()
      
      ' We are initializing our jump table. Note that the labels
      ' will be placed later using the MarkLabel method. 

      Dim jumpTable() As Label = {myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel()}
      
      ' arg0, the number we passed, is pushed onto the stack.
      ' In this case, due to the design of the code sample,
      ' the value pushed onto the stack happens to match the
      ' index of the label (in IL terms, the index of the offset
      ' in the jump table). If this is not the case, such as
      ' when switching based on non-integer values, rules for the correspondence
      ' between the possible case values and each index of the offsets
      ' must be established outside of the ILGenerator.Emit calls,
      ' much as a compiler would.

      myIL.Emit(OpCodes.Ldarg_0)
      myIL.Emit(OpCodes.Switch, jumpTable)
      
      ' Branch on default case
      myIL.Emit(OpCodes.Br_S, defaultCase)
      
      ' Case arg0 = 0
      myIL.MarkLabel(jumpTable(0))
      myIL.Emit(OpCodes.Ldstr, "are no bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 1
      myIL.MarkLabel(jumpTable(1))
      myIL.Emit(OpCodes.Ldstr, "is one banana")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 2
      myIL.MarkLabel(jumpTable(2))
      myIL.Emit(OpCodes.Ldstr, "are two bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 3
      myIL.MarkLabel(jumpTable(3))
      myIL.Emit(OpCodes.Ldstr, "are three bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 4
      myIL.MarkLabel(jumpTable(4))
      myIL.Emit(OpCodes.Ldstr, "are four bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Default case
      myIL.MarkLabel(defaultCase)
      myIL.Emit(OpCodes.Ldstr, "are many bananas")
      
      myIL.MarkLabel(endOfMethod)
      myIL.Emit(OpCodes.Ret)
      
      Return myTypeBuilder.CreateType()

   End Function 'BuildMyType
    
   
   Public Shared Sub Main()

      Dim myType As Type = BuildMyType()
      
      Console.Write("Enter an integer between 0 and 5: ")
      Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
      
      Console.WriteLine("---")
      Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
      Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
                         BindingFlags.InvokeMethod, Nothing, _
                             myInstance, New Object() {theValue}))

   End Sub

End Class

Comentários

Emite uma tabela de comutador.

Os valores de instrução são definidos na OpCodes enumeração.

Os rótulos são criados usando DefineLabel e sua localização dentro do fluxo é corrigida usando MarkLabel. Se uma instrução de byte único for usada, o rótulo poderá representar um salto de no máximo 127 bytes ao longo do fluxo. opcode deve representar uma instrução de ramificação. Como os branches são instruções relativas, label serão substituídos pelo deslocamento correto para ramificação durante o processo de correção.

Aplica-se a

Emit(OpCode, MethodInfo)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo msil (linguagem intermediária) Microsoft seguido pelo token de metadados para o método fornecido.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::MethodInfo ^ meth);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::MethodInfo ^ meth);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
Public MustOverride Sub Emit (opcode As OpCode, meth As MethodInfo)
Public Overridable Sub Emit (opcode As OpCode, meth As MethodInfo)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

meth
MethodInfo

Um MethodInfo que representa um método.

Exceções

meth é null.

meth é um método genérico para o qual a IsGenericMethodDefinition propriedade é false.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

O local do qual é registrado para que o fluxo de meth instruções possa ser corrigido, se necessário, ao persistir o módulo em um arquivo PE (executável portátil).

Se meth representar um método genérico, ele deverá ser uma definição de método genérico. Ou seja, sua propriedade MethodInfo.IsGenericMethodDefinition deve ser true.

Aplica-se a

Emit(OpCode, ConstructorInfo)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o token de metadados do construtor especificado no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::ConstructorInfo ^ con);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::ConstructorInfo ^ con);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
[System.Runtime.InteropServices.ComVisible(true)]
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
[<System.Runtime.InteropServices.ComVisible(true)>]
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
Public MustOverride Sub Emit (opcode As OpCode, con As ConstructorInfo)
Public Overridable Sub Emit (opcode As OpCode, con As ConstructorInfo)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

con
ConstructorInfo

Um ConstructorInfo construtor que representa.

Atributos

Exceções

con é null.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

O local do qual é registrado para que o fluxo de con instruções possa ser corrigido, se necessário, ao persistir o módulo em um arquivo PE (executável portátil).

Aplica-se a

Emit(OpCode, Int64)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, long arg);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, long arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, long arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, long arg);
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int64 -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Long)
Public Overridable Sub Emit (opcode As OpCode, arg As Long)

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo.

arg
Int64

O argumento numérico foi enviado para o fluxo imediatamente após a instrução.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, Int32)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, int arg);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, int arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, int arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, int arg);
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
override this.Emit : System.Reflection.Emit.OpCode * int -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Integer)
Public Overridable Sub Emit (opcode As OpCode, arg As Integer)

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo.

arg
Int32

O argumento numérico foi enviado para o fluxo imediatamente após a instrução.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, Int16)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, short arg);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, short arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, short arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, short arg);
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int16 -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Short)
Public Overridable Sub Emit (opcode As OpCode, arg As Short)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

arg
Int16

O Int argumento foi enviado para o fluxo imediatamente após a instrução.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, Double)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o argumento numérico no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, double arg);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, double arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, double arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, double arg);
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
override this.Emit : System.Reflection.Emit.OpCode * double -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Double)
Public Overridable Sub Emit (opcode As OpCode, arg As Double)

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo. Definido na OpCodes enumeração.

arg
Double

O argumento numérico foi enviado para o fluxo imediatamente após a instrução.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode, Byte)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada e o argumento de caractere no fluxo de instruções da MSIL (linguagem intermediária) Microsoft.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, byte arg);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, byte arg);
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
override this.Emit : System.Reflection.Emit.OpCode * byte -> unit
Public MustOverride Sub Emit (opcode As OpCode, arg As Byte)
Public Overridable Sub Emit (opcode As OpCode, arg As Byte)

Parâmetros

opcode
OpCode

A instrução MSIL a ser colocada no fluxo.

arg
Byte

O argumento de caractere enviado para o fluxo imediatamente após a instrução.

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Aplica-se a

Emit(OpCode)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo de instruções.

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

Parâmetros

opcode
OpCode

A instrução Microsoft Linguagem Intermediária (MSIL) a ser colocada no fluxo.

Exemplos

O exemplo de código abaixo demonstra o uso de Emit gerar saída MSIL por meio de uma instância de ILGenerator.

using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;

class DynamicJumpTableDemo
{
   public static Type BuildMyType()
   {
    AppDomain myDomain = Thread.GetDomain();
    AssemblyName myAsmName = new AssemblyName();
    myAsmName.Name = "MyDynamicAssembly";

    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                        myAsmName,
                        AssemblyBuilderAccess.Run);
    ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
                        "MyJumpTableDemo");

    TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
                            TypeAttributes.Public);
    MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
                             MethodAttributes.Public |
                             MethodAttributes.Static,
                                             typeof(string),
                                             new Type[] {typeof(int)});

    ILGenerator myIL = myMthdBuilder.GetILGenerator();

    Label defaultCase = myIL.DefineLabel();	
    Label endOfMethod = myIL.DefineLabel();	

    // We are initializing our jump table. Note that the labels
    // will be placed later using the MarkLabel method.

    Label[] jumpTable = new Label[] { myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel() };

    // arg0, the number we passed, is pushed onto the stack.
    // In this case, due to the design of the code sample,
    // the value pushed onto the stack happens to match the
    // index of the label (in IL terms, the index of the offset
    // in the jump table). If this is not the case, such as
    // when switching based on non-integer values, rules for the correspondence
    // between the possible case values and each index of the offsets
    // must be established outside of the ILGenerator.Emit calls,
    // much as a compiler would.

    myIL.Emit(OpCodes.Ldarg_0);
    myIL.Emit(OpCodes.Switch, jumpTable);
    
    // Branch on default case
    myIL.Emit(OpCodes.Br_S, defaultCase);

    // Case arg0 = 0
    myIL.MarkLabel(jumpTable[0]);
    myIL.Emit(OpCodes.Ldstr, "are no bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 1
    myIL.MarkLabel(jumpTable[1]);
    myIL.Emit(OpCodes.Ldstr, "is one banana");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 2
    myIL.MarkLabel(jumpTable[2]);
    myIL.Emit(OpCodes.Ldstr, "are two bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 3
    myIL.MarkLabel(jumpTable[3]);
    myIL.Emit(OpCodes.Ldstr, "are three bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 4
    myIL.MarkLabel(jumpTable[4]);
    myIL.Emit(OpCodes.Ldstr, "are four bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Default case
    myIL.MarkLabel(defaultCase);
    myIL.Emit(OpCodes.Ldstr, "are many bananas");

    myIL.MarkLabel(endOfMethod);
    myIL.Emit(OpCodes.Ret);
    
    return myTypeBuilder.CreateType();
   }

   public static void Main()
   {
    Type myType = BuildMyType();
    
    Console.Write("Enter an integer between 0 and 5: ");
    int theValue = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("---");
    Object myInstance = Activator.CreateInstance(myType, new object[0]);	
    Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
                               BindingFlags.InvokeMethod,
                               null,
                               myInstance,
                               new object[] {theValue}));
   }
}

Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit

 _

Class DynamicJumpTableDemo
   
   Public Shared Function BuildMyType() As Type

      Dim myDomain As AppDomain = Thread.GetDomain()
      Dim myAsmName As New AssemblyName()
      myAsmName.Name = "MyDynamicAssembly"
      
      Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
                            AssemblyBuilderAccess.Run)
      Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
      
      Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
                                 TypeAttributes.Public)
      Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
                        MethodAttributes.Public Or MethodAttributes.Static, _
                        GetType(String), New Type() {GetType(Integer)})
      
      Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
      
      Dim defaultCase As Label = myIL.DefineLabel()
      Dim endOfMethod As Label = myIL.DefineLabel()
      
      ' We are initializing our jump table. Note that the labels
      ' will be placed later using the MarkLabel method. 

      Dim jumpTable() As Label = {myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel()}
      
      ' arg0, the number we passed, is pushed onto the stack.
      ' In this case, due to the design of the code sample,
      ' the value pushed onto the stack happens to match the
      ' index of the label (in IL terms, the index of the offset
      ' in the jump table). If this is not the case, such as
      ' when switching based on non-integer values, rules for the correspondence
      ' between the possible case values and each index of the offsets
      ' must be established outside of the ILGenerator.Emit calls,
      ' much as a compiler would.

      myIL.Emit(OpCodes.Ldarg_0)
      myIL.Emit(OpCodes.Switch, jumpTable)
      
      ' Branch on default case
      myIL.Emit(OpCodes.Br_S, defaultCase)
      
      ' Case arg0 = 0
      myIL.MarkLabel(jumpTable(0))
      myIL.Emit(OpCodes.Ldstr, "are no bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 1
      myIL.MarkLabel(jumpTable(1))
      myIL.Emit(OpCodes.Ldstr, "is one banana")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 2
      myIL.MarkLabel(jumpTable(2))
      myIL.Emit(OpCodes.Ldstr, "are two bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 3
      myIL.MarkLabel(jumpTable(3))
      myIL.Emit(OpCodes.Ldstr, "are three bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 4
      myIL.MarkLabel(jumpTable(4))
      myIL.Emit(OpCodes.Ldstr, "are four bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Default case
      myIL.MarkLabel(defaultCase)
      myIL.Emit(OpCodes.Ldstr, "are many bananas")
      
      myIL.MarkLabel(endOfMethod)
      myIL.Emit(OpCodes.Ret)
      
      Return myTypeBuilder.CreateType()

   End Function 'BuildMyType
    
   
   Public Shared Sub Main()

      Dim myType As Type = BuildMyType()
      
      Console.Write("Enter an integer between 0 and 5: ")
      Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
      
      Console.WriteLine("---")
      Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
      Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
                         BindingFlags.InvokeMethod, Nothing, _
                             myInstance, New Object() {theValue}))

   End Sub

End Class

Comentários

Se o opcode parâmetro exigir um argumento, o chamador deverá garantir que o comprimento do argumento corresponda ao comprimento do parâmetro declarado. Caso contrário, os resultados serão imprevisíveis. Por exemplo, se a instrução Emit exigir um operando de 2 bytes e o chamador fornecer um operando de 4 bytes, o runtime emitirá dois bytes adicionais para o fluxo de instruções. Esses bytes extras serão Nop instruções.

Os valores de instrução são definidos em OpCodes.

Aplica-se a

Emit(OpCode, Label)

Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs
Origem:
ILGenerator.cs

Coloca a instrução especificada no fluxo de Microsoft linguagem intermediária (MSIL) e deixa espaço para incluir um rótulo quando as correções forem feitas.

public:
 abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::Label label);
public:
 virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::Label label);
public abstract void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
Public MustOverride Sub Emit (opcode As OpCode, label As Label)
Public Overridable Sub Emit (opcode As OpCode, label As Label)

Parâmetros

opcode
OpCode

A instrução MSIL a ser emitida no fluxo.

label
Label

O rótulo para o qual ramificar a partir desse local.

Exemplos

O exemplo de código abaixo ilustra a criação de um método dinâmico com uma tabela de salto. A tabela de salto é criada usando uma matriz de Label.

using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;

class DynamicJumpTableDemo
{
   public static Type BuildMyType()
   {
    AppDomain myDomain = Thread.GetDomain();
    AssemblyName myAsmName = new AssemblyName();
    myAsmName.Name = "MyDynamicAssembly";

    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                        myAsmName,
                        AssemblyBuilderAccess.Run);
    ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
                        "MyJumpTableDemo");

    TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
                            TypeAttributes.Public);
    MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
                             MethodAttributes.Public |
                             MethodAttributes.Static,
                                             typeof(string),
                                             new Type[] {typeof(int)});

    ILGenerator myIL = myMthdBuilder.GetILGenerator();

    Label defaultCase = myIL.DefineLabel();	
    Label endOfMethod = myIL.DefineLabel();	

    // We are initializing our jump table. Note that the labels
    // will be placed later using the MarkLabel method.

    Label[] jumpTable = new Label[] { myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel() };

    // arg0, the number we passed, is pushed onto the stack.
    // In this case, due to the design of the code sample,
    // the value pushed onto the stack happens to match the
    // index of the label (in IL terms, the index of the offset
    // in the jump table). If this is not the case, such as
    // when switching based on non-integer values, rules for the correspondence
    // between the possible case values and each index of the offsets
    // must be established outside of the ILGenerator.Emit calls,
    // much as a compiler would.

    myIL.Emit(OpCodes.Ldarg_0);
    myIL.Emit(OpCodes.Switch, jumpTable);
    
    // Branch on default case
    myIL.Emit(OpCodes.Br_S, defaultCase);

    // Case arg0 = 0
    myIL.MarkLabel(jumpTable[0]);
    myIL.Emit(OpCodes.Ldstr, "are no bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 1
    myIL.MarkLabel(jumpTable[1]);
    myIL.Emit(OpCodes.Ldstr, "is one banana");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 2
    myIL.MarkLabel(jumpTable[2]);
    myIL.Emit(OpCodes.Ldstr, "are two bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 3
    myIL.MarkLabel(jumpTable[3]);
    myIL.Emit(OpCodes.Ldstr, "are three bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 4
    myIL.MarkLabel(jumpTable[4]);
    myIL.Emit(OpCodes.Ldstr, "are four bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Default case
    myIL.MarkLabel(defaultCase);
    myIL.Emit(OpCodes.Ldstr, "are many bananas");

    myIL.MarkLabel(endOfMethod);
    myIL.Emit(OpCodes.Ret);
    
    return myTypeBuilder.CreateType();
   }

   public static void Main()
   {
    Type myType = BuildMyType();
    
    Console.Write("Enter an integer between 0 and 5: ");
    int theValue = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("---");
    Object myInstance = Activator.CreateInstance(myType, new object[0]);	
    Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
                               BindingFlags.InvokeMethod,
                               null,
                               myInstance,
                               new object[] {theValue}));
   }
}

Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit

 _

Class DynamicJumpTableDemo
   
   Public Shared Function BuildMyType() As Type

      Dim myDomain As AppDomain = Thread.GetDomain()
      Dim myAsmName As New AssemblyName()
      myAsmName.Name = "MyDynamicAssembly"
      
      Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
                            AssemblyBuilderAccess.Run)
      Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
      
      Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
                                 TypeAttributes.Public)
      Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
                        MethodAttributes.Public Or MethodAttributes.Static, _
                        GetType(String), New Type() {GetType(Integer)})
      
      Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
      
      Dim defaultCase As Label = myIL.DefineLabel()
      Dim endOfMethod As Label = myIL.DefineLabel()
      
      ' We are initializing our jump table. Note that the labels
      ' will be placed later using the MarkLabel method. 

      Dim jumpTable() As Label = {myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel(), _
                  myIL.DefineLabel()}
      
      ' arg0, the number we passed, is pushed onto the stack.
      ' In this case, due to the design of the code sample,
      ' the value pushed onto the stack happens to match the
      ' index of the label (in IL terms, the index of the offset
      ' in the jump table). If this is not the case, such as
      ' when switching based on non-integer values, rules for the correspondence
      ' between the possible case values and each index of the offsets
      ' must be established outside of the ILGenerator.Emit calls,
      ' much as a compiler would.

      myIL.Emit(OpCodes.Ldarg_0)
      myIL.Emit(OpCodes.Switch, jumpTable)
      
      ' Branch on default case
      myIL.Emit(OpCodes.Br_S, defaultCase)
      
      ' Case arg0 = 0
      myIL.MarkLabel(jumpTable(0))
      myIL.Emit(OpCodes.Ldstr, "are no bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 1
      myIL.MarkLabel(jumpTable(1))
      myIL.Emit(OpCodes.Ldstr, "is one banana")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 2
      myIL.MarkLabel(jumpTable(2))
      myIL.Emit(OpCodes.Ldstr, "are two bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 3
      myIL.MarkLabel(jumpTable(3))
      myIL.Emit(OpCodes.Ldstr, "are three bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Case arg0 = 4
      myIL.MarkLabel(jumpTable(4))
      myIL.Emit(OpCodes.Ldstr, "are four bananas")
      myIL.Emit(OpCodes.Br_S, endOfMethod)
      
      ' Default case
      myIL.MarkLabel(defaultCase)
      myIL.Emit(OpCodes.Ldstr, "are many bananas")
      
      myIL.MarkLabel(endOfMethod)
      myIL.Emit(OpCodes.Ret)
      
      Return myTypeBuilder.CreateType()

   End Function 'BuildMyType
    
   
   Public Shared Sub Main()

      Dim myType As Type = BuildMyType()
      
      Console.Write("Enter an integer between 0 and 5: ")
      Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
      
      Console.WriteLine("---")
      Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
      Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
                         BindingFlags.InvokeMethod, Nothing, _
                             myInstance, New Object() {theValue}))

   End Sub

End Class

Comentários

Os valores de instrução são definidos na OpCodes enumeração.

Os rótulos são criados usando DefineLabele sua localização dentro do fluxo é corrigida usando MarkLabel. Se uma instrução de byte único for usada, o rótulo poderá representar um salto de no máximo 127 bytes ao longo do fluxo. opcode deve representar uma instrução de ramificação. Como os branches são instruções relativas, label serão substituídos pelo deslocamento correto para ramificação durante o processo de correção.

Aplica-se a