Прочитать на английском

Поделиться через


ILGenerator.Emit Метод

Определение

Помещает инструкцию в поток языка MSIL для JIT-компилятора.

Перегрузки

Emit(OpCode, LocalBuilder)

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует индекс заданной локальной переменной.

Emit(OpCode, Type)

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует маркер метаданных для указанного типа.

Emit(OpCode, String)

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует маркер метаданных указанной строки.

Emit(OpCode, Single)

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

Emit(OpCode, SByte)

Помещает заданную инструкцию и символьный аргумент в поток инструкций языка MSIL.

Emit(OpCode, MethodInfo)

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует маркер метаданных указанного метода.

Emit(OpCode, SignatureHelper)

Помещает заданную инструкцию и токен подписи в поток инструкций языка MSIL.

Emit(OpCode, Label[])

Помещает указанную инструкцию в поток инструкций языка MSIL и оставляет место, чтобы после того, как будут произведены необходимые настройки, можно было включить метку.

Emit(OpCode, FieldInfo)

Помещает заданную инструкцию и маркер метаданных указанного поля в поток инструкций языка MSIL.

Emit(OpCode, ConstructorInfo)

Помещает заданную инструкцию и маркер метаданных указанного конструктора в поток инструкций языка MSIL.

Emit(OpCode, Int64)

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

Emit(OpCode, Int32)

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

Emit(OpCode, Int16)

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

Emit(OpCode, Double)

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

Emit(OpCode, Byte)

Помещает заданную инструкцию и символьный аргумент в поток инструкций языка MSIL.

Emit(OpCode)

Помещает указанную инструкцию в поток инструкций.

Emit(OpCode, Label)

Помещает указанную инструкцию в поток инструкций языка MSIL и оставляет место, чтобы после того, как будут произведены необходимые настройки, можно было включить метку.

Emit(OpCode, LocalBuilder)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует индекс заданной локальной переменной.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

local
LocalBuilder

Локальная переменная.

Исключения

Родительский метод параметра local не соответствует методу, связанному с объектом ILGenerator.

local имеет значение null.

opcode представляет собой 1-байтную инструкцию, а local представляет локальную переменную с индексом большим, чем значение Byte.MaxValue.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Type)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует маркер метаданных для указанного типа.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, Type cls);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, Type cls);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток.

cls
Type

Объект Type.

Исключения

cls имеет значение null.

Комментарии

Значения инструкций определяются в перечислении OpCodes . Расположение cls записывается, чтобы при необходимости можно было исправить маркер при сохранении модуля в переносимом исполняемом файле (PE).

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, String)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует маркер метаданных указанной строки.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, string str);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, string str);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

str
String

Объект String, который подлежит выпуску.

Комментарии

Значения инструкций определяются в перечислении OpCodes . Расположение записывается для будущих str исправлений, если модуль сохраняется в переносимом исполняемом файле (PE).

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Single)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, float arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, float arg);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток.

arg
Single

Аргумент типа Single, помещаемый в поток сразу после инструкции.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, SByte)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Важно!

Этот API несовместим с CLS.

Помещает заданную инструкцию и символьный аргумент в поток инструкций языка MSIL.

C#
[System.CLSCompliant(false)]
public void Emit (System.Reflection.Emit.OpCode opcode, sbyte arg);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток.

arg
SByte

Аргумент типа character, помещаемый в поток сразу после инструкции.

Атрибуты

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, MethodInfo)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает в поток инструкций языка MSIL заданную инструкцию, за которой следует маркер метаданных указанного метода.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

meth
MethodInfo

Объект MethodInfo, предоставляющий метод.

Исключения

meth имеет значение null.

meth является универсальным методом, для которого значение свойства IsGenericMethodDefinition равно false.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Расположение meth записывается, чтобы при необходимости можно было исправить поток инструкций при сохранении модуля в переносимом исполняемом файле (PE).

Если meth представляет универсальный метод, он должен быть определением универсального метода. То есть свойство MethodInfo.IsGenericMethodDefinition должно иметь значение true.

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, SignatureHelper)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и токен подписи в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

signature
SignatureHelper

Вспомогательный класс для конструирования токена подписи.

Исключения

signature имеет значение null.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Label[])

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает указанную инструкцию в поток инструкций языка MSIL и оставляет место, чтобы после того, как будут произведены необходимые настройки, можно было включить метку.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

labels
Label[]

Массив объектов меток, на которые следует осуществлять переход из данного места. Задействуются все метки.

Исключения

con имеет значение null. Это исключение является новым в платформа .NET Framework 4.

Примеры

В приведенном ниже примере кода показано создание динамического метода с таблицей переходов. Таблица переходов создается с помощью массива Label.

C#
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}));
   }
}

Комментарии

Создает таблицу переключения.

Значения инструкций определяются в перечислении OpCodes .

Метки создаются с помощью , DefineLabel а их расположение в потоке фиксируется с помощью MarkLabel. Если используется однобайтовая инструкция, метка может представлять скачок не более 127 байт в потоке. opcode должен представлять ветвь инструкции. Так как ветви являются относительными инструкциями, label они будут заменены правильным смещением в ветвь в процессе исправления.

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, FieldInfo)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и маркер метаданных указанного поля в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

field
FieldInfo

Объект FieldInfo, представляющий поле.

Комментарии

Значения инструкций определяются в перечислении OpCodes . Расположение field записывается, чтобы при необходимости можно было исправить поток инструкций при сохранении модуля в переносимом исполняемом файле (PE).

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, ConstructorInfo)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и маркер метаданных указанного конструктора в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
C#
[System.Runtime.InteropServices.ComVisible(true)]
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

con
ConstructorInfo

Объект ConstructorInfo, представляющий конструктор.

Атрибуты

Исключения

con имеет значение null. Это исключение является новым в платформа .NET Framework 4.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Расположение записывается, чтобы при необходимости можно было исправить поток инструкций con при сохранении модуля в переносимом исполняемом файле (PE).

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Int64)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, long arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, long arg);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток.

arg
Int64

Числовой аргумент, помещаемый в поток сразу после инструкции.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Int32)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, int arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, int arg);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток.

arg
Int32

Числовой аргумент, помещаемый в поток сразу после инструкции.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Int16)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, short arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, short arg);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

arg
Int16

Аргумент типа Int, помещаемый в поток сразу после инструкции.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Double)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и числовой аргумент в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, double arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, double arg);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток. Определена в перечислении OpCodes.

arg
Double

Числовой аргумент, помещаемый в поток сразу после инструкции.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Byte)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает заданную инструкцию и символьный аргумент в поток инструкций языка MSIL.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, byte arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, byte arg);

Параметры

opcode
OpCode

Инструкция MSIL, помещаемая в поток.

arg
Byte

Аргумент типа character, помещаемый в поток сразу после инструкции.

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает указанную инструкцию в поток инструкций.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode);

Параметры

opcode
OpCode

Инструкция языка MSIL, помещаемая в поток.

Примеры

В приведенном ниже примере кода показано использование для создания выходных Emit данных MSIL с помощью экземпляра ILGenerator.

C#
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}));
   }
}

Комментарии

Если параметр opcode требует аргумента, вызывающий объект должен убедиться, что длина аргумента совпадает с длиной объявленного параметра. В противном случае результаты будут непредсказуемыми. Например, если инструкции Emit требуется 2-байтовый операнд, а вызывающий объект предоставляет 4-байтовый операнд, среда выполнения выдаст два дополнительных байта в поток инструкции. Эти дополнительные байты будут Nop инструкциями.

Значения инструкций определяются в OpCodes.

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Label)

Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs
Исходный код:
ILGenerator.cs

Помещает указанную инструкцию в поток инструкций языка MSIL и оставляет место, чтобы после того, как будут произведены необходимые настройки, можно было включить метку.

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);

Параметры

opcode
OpCode

Инструкция языка MSIL, которую следует включить в поток.

label
Label

Метка, на которую следует осуществить переход из данного места.

Примеры

В приведенном ниже примере кода показано создание динамического метода с таблицей перехода. Таблица переходов создается с помощью массива Label.

C#
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}));
   }
}

Комментарии

Значения инструкций определяются в перечислении OpCodes .

Метки создаются с помощью DefineLabel, а их расположение в потоке фиксируется с помощью MarkLabel. Если используется однобайтовая инструкция, метка может представлять скачок не более 127 байт в потоке. opcode должен представлять инструкцию ветви. Так как ветви являются относительными инструкциями, label в процессе исправления они будут заменены правильным смещением в ветвь.

Применяется к

.NET 9 и другие версии
Продукт Версии
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1