ILGenerator.Emit 메서드
정의
중요
일부 정보는 릴리스되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적이거나 묵시적인 보증도 하지 않습니다.
JIT(Just-In-Time) 컴파일러에 대한 MSIL(Microsoft Intermediate Language) 스트림에 명령을 배치합니다.
오버로드
Emit(OpCode, LocalBuilder) |
MSIL(Microsoft Intermediate Language) 스트림에 지정된 명령을 배치합니다. 해당 스트림 다음에는 지정된 지역 변수에 대한 메타데이터 인덱스가 옵니다. |
Emit(OpCode, Type) |
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치합니다. 해당 스트림 다음에는 지정한 형식에 대한 메타데이터 토큰이 옵니다. |
Emit(OpCode, String) |
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치합니다. 해당 스트림 다음에는 지정한 문자열에 대한 메타데이터 토큰이 옵니다. |
Emit(OpCode, Single) |
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode, SByte) |
지정된 명령 및 문자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode, MethodInfo) |
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치합니다. 해당 스트림 다음에는 지정한 메서드에 대한 메타데이터 토큰이 옵니다. |
Emit(OpCode, SignatureHelper) |
MSIL(Microsoft Intermediate Language) 명령 스트림에 지정된 명령 및 시그니처 토큰을 배치합니다. |
Emit(OpCode, Label[]) |
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치하고 고정이 완료되면 레이블을 포함할 공간을 남겨 둡니다. |
Emit(OpCode, FieldInfo) |
MSIL(Microsoft Intermediate Language) 명령 스트림에 지정된 명령 및 지정된 필드에 대한 메타데이터 토큰을 배치합니다. |
Emit(OpCode, ConstructorInfo) |
MSIL(Microsoft Intermediate Language) 명령 스트림에 지정된 명령 및 지정된 생성자에 대한 메타데이터 토큰을 배치합니다. |
Emit(OpCode, Int64) |
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode, Int32) |
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode, Int16) |
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode, Double) |
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode, Byte) |
지정된 명령 및 문자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다. |
Emit(OpCode) |
명령 스트림에 지정된 명령을 배치합니다. |
Emit(OpCode, Label) |
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치하고 고정이 완료되면 레이블을 포함할 공간을 남겨 둡니다. |
Emit(OpCode, LocalBuilder)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
MSIL(Microsoft Intermediate Language) 스트림에 지정된 명령을 배치합니다. 해당 스트림 다음에는 지정된 지역 변수에 대한 메타데이터 인덱스가 옵니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::LocalBuilder ^ local);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::LocalBuilder ^ local);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.LocalBuilder -> unit
Public Overridable Sub Emit (opcode As OpCode, local As LocalBuilder)
Public MustOverride Sub Emit (opcode As OpCode, local As LocalBuilder)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- local
- LocalBuilder
지역 변수입니다.
예외
local
매개 변수의 부모 메서드가 해당 ILGenerator에 연결된 메서드와 일치하지 않는 경우
local
이(가) null
인 경우
opcode
가 싱글바이트 명령이며 local
이 Byte.MaxValue
보다 큰 인덱스의 지역 변수를 나타내는 경우
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, Type)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치합니다. 해당 스트림 다음에는 지정한 형식에 대한 메타데이터 토큰이 옵니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, Type ^ cls);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, Type ^ cls);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, Type cls);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, Type cls);
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
override this.Emit : System.Reflection.Emit.OpCode * Type -> unit
abstract member Emit : System.Reflection.Emit.OpCode * Type -> unit
Public Overridable Sub Emit (opcode As OpCode, cls As Type)
Public MustOverride Sub Emit (opcode As OpCode, cls As Type)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
- cls
- Type
Type
예외
cls
은 null
입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다. 의 위치 cls
는 모듈을 PE(이식 가능한 실행 파일) 파일에 유지할 때 필요한 경우 토큰을 패치할 수 있도록 기록됩니다.
적용 대상
Emit(OpCode, String)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치합니다. 해당 스트림 다음에는 지정한 문자열에 대한 메타데이터 토큰이 옵니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::String ^ str);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, string str);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, string str);
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
override this.Emit : System.Reflection.Emit.OpCode * string -> unit
abstract member Emit : System.Reflection.Emit.OpCode * string -> unit
Public Overridable Sub Emit (opcode As OpCode, str As String)
Public MustOverride Sub Emit (opcode As OpCode, str As String)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- str
- String
내보낼 String
입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다. 모듈이 PE(이식 가능한 실행 파일) 파일에 유지되는 경우 의 위치 str
는 향후 수정을 위해 기록됩니다.
적용 대상
Emit(OpCode, Single)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, float arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, float arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, float arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, float arg);
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
override this.Emit : System.Reflection.Emit.OpCode * single -> unit
abstract member Emit : System.Reflection.Emit.OpCode * single -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Single)
Public MustOverride Sub Emit (opcode As OpCode, arg As Single)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, SByte)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
중요
이 API는 CLS 규격이 아닙니다.
지정된 명령 및 문자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
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)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
- arg
- SByte
명령 바로 다음에 스트림으로 푸시되는 문자 인수입니다.
- 특성
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, MethodInfo)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치합니다. 해당 스트림 다음에는 지정한 메서드에 대한 메타데이터 토큰이 옵니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::MethodInfo ^ meth);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::MethodInfo ^ meth);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.MethodInfo -> unit
Public Overridable Sub Emit (opcode As OpCode, meth As MethodInfo)
Public MustOverride Sub Emit (opcode As OpCode, meth As MethodInfo)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- meth
- MethodInfo
메서드를 나타내는 MethodInfo
입니다.
예외
meth
이(가) null
인 경우
meth
가 IsGenericMethodDefinition 속성이 false
인 제네릭 메서드인 경우
설명
명령 값은 열거형에 OpCodes
정의됩니다.
모듈을 meth
PE(이식 가능한 실행 파일) 파일에 유지할 때 필요한 경우 명령 스트림을 패치할 수 있도록 의 위치가 기록됩니다.
제네릭 메서드를 나타내는 경우 meth
제네릭 메서드 정의여야 합니다. 즉, MethodInfo.IsGenericMethodDefinition 속성은 이어야 true
합니다.
적용 대상
Emit(OpCode, SignatureHelper)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
MSIL(Microsoft Intermediate Language) 명령 스트림에 지정된 명령 및 시그니처 토큰을 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::SignatureHelper ^ signature);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::SignatureHelper ^ signature);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.SignatureHelper -> unit
Public Overridable Sub Emit (opcode As OpCode, signature As SignatureHelper)
Public MustOverride Sub Emit (opcode As OpCode, signature As SignatureHelper)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- signature
- SignatureHelper
시그니처 토큰을 생성하는 도우미입니다.
예외
signature
이(가) null
인 경우
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, Label[])
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치하고 고정이 완료되면 레이블을 포함할 공간을 남겨 둡니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, cli::array <System::Reflection::Emit::Label> ^ labels);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, cli::array <System::Reflection::Emit::Label> ^ labels);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label[] -> unit
Public Overridable Sub Emit (opcode As OpCode, labels As Label())
Public MustOverride Sub Emit (opcode As OpCode, labels As Label())
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- labels
- Label[]
이 위치에서 분기될 레이블 개체 배열입니다. 모든 레이블을 사용합니다.
예외
con
이(가) null
인 경우 이 예외는 .NET Framework 4의 새로운 기능입니다.
예제
아래 코드 샘플에서는 점프 테이블을 사용하여 동적 메서드를 만드는 방법을 보여 줍니다. 점프 테이블은 배열을 사용하여 빌드됩니다 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.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
설명
스위치 테이블을 내보낸다.
명령 값은 열거형에 OpCodes
정의됩니다.
레이블은 를 사용하여 DefineLabel 만들어지고 스트림 내의 위치는 를 사용하여 MarkLabel수정됩니다. 단일 바이트 명령을 사용하는 경우 레이블은 스트림을 따라 최대 127바이트의 점프를 나타낼 수 있습니다.
opcode
는 분기 명령을 나타내야 합니다. 분기는 상대 지침 label
이므로 는 수정 프로세스 중에 분기에 대한 올바른 오프셋으로 바뀝니다.
적용 대상
Emit(OpCode, FieldInfo)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
MSIL(Microsoft Intermediate Language) 명령 스트림에 지정된 명령 및 지정된 필드에 대한 메타데이터 토큰을 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::FieldInfo ^ field);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::FieldInfo ^ field);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.FieldInfo -> unit
Public Overridable Sub Emit (opcode As OpCode, field As FieldInfo)
Public MustOverride Sub Emit (opcode As OpCode, field As FieldInfo)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- field
- FieldInfo
필드를 나타내는 FieldInfo
입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다. 모듈을 field
PE(이식 가능한 실행 파일) 파일에 유지할 때 필요한 경우 명령 스트림을 패치할 수 있도록 의 위치가 기록됩니다.
적용 대상
Emit(OpCode, ConstructorInfo)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
MSIL(Microsoft Intermediate Language) 명령 스트림에 지정된 명령 및 지정된 생성자에 대한 메타데이터 토큰을 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::ConstructorInfo ^ con);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::ConstructorInfo ^ con);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
[System.Runtime.InteropServices.ComVisible(true)]
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
[<System.Runtime.InteropServices.ComVisible(true)>]
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.ConstructorInfo -> unit
Public Overridable Sub Emit (opcode As OpCode, con As ConstructorInfo)
Public MustOverride Sub Emit (opcode As OpCode, con As ConstructorInfo)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- con
- ConstructorInfo
생성자를 나타내는 ConstructorInfo
입니다.
- 특성
예외
con
은 null
입니다. 이 예외는 .NET Framework 4의 새로운 기능입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
모듈을 con
PE(이식 가능한 실행 파일) 파일에 유지할 때 필요한 경우 명령 스트림을 패치할 수 있도록 의 위치가 기록됩니다.
적용 대상
Emit(OpCode, Int64)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, long arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, long arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, long arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, long arg);
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int64 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int64 -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Long)
Public MustOverride Sub Emit (opcode As OpCode, arg As Long)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
- arg
- Int64
명령 바로 다음에 스트림으로 푸시되는 숫자 인수입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, Int32)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, int arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, int arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, int arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, int arg);
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
override this.Emit : System.Reflection.Emit.OpCode * int -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Integer)
Public MustOverride Sub Emit (opcode As OpCode, arg As Integer)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
- arg
- Int32
명령 바로 다음에 스트림으로 푸시되는 숫자 인수입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, Int16)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, short arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, short arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, short arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, short arg);
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
override this.Emit : System.Reflection.Emit.OpCode * int16 -> unit
abstract member Emit : System.Reflection.Emit.OpCode * int16 -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Short)
Public MustOverride Sub Emit (opcode As OpCode, arg As Short)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- arg
- Int16
명령 바로 다음에 스트림으로 푸시되는 Int
인수입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, Double)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령 및 숫자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, double arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, double arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, double arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, double arg);
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
override this.Emit : System.Reflection.Emit.OpCode * double -> unit
abstract member Emit : System.Reflection.Emit.OpCode * double -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Double)
Public MustOverride Sub Emit (opcode As OpCode, arg As Double)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
OpCodes
열거형에 정의됩니다.
- arg
- Double
명령 바로 다음에 스트림으로 푸시되는 숫자 인수입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode, Byte)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령 및 문자 인수를 MSIL(Microsoft Intermediate Language) 명령 스트림에 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Byte arg);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, byte arg);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, byte arg);
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
override this.Emit : System.Reflection.Emit.OpCode * byte -> unit
abstract member Emit : System.Reflection.Emit.OpCode * byte -> unit
Public Overridable Sub Emit (opcode As OpCode, arg As Byte)
Public MustOverride Sub Emit (opcode As OpCode, arg As Byte)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL 명령입니다.
- arg
- Byte
명령 바로 다음에 스트림으로 푸시되는 문자 인수입니다.
설명
명령 값은 열거형에 OpCodes
정의됩니다.
적용 대상
Emit(OpCode)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
명령 스트림에 지정된 명령을 배치합니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode);
public virtual void Emit (System.Reflection.Emit.OpCode opcode);
public abstract void Emit (System.Reflection.Emit.OpCode opcode);
abstract member Emit : System.Reflection.Emit.OpCode -> unit
override this.Emit : System.Reflection.Emit.OpCode -> unit
abstract member Emit : System.Reflection.Emit.OpCode -> unit
Public Overridable Sub Emit (opcode As OpCode)
Public MustOverride Sub Emit (opcode As OpCode)
매개 변수
- opcode
- OpCode
스트림에 배치될 MSIL(Microsoft Intermediate Language) 명령입니다.
예제
아래 코드 샘플에서는 를 사용하여 의 Emit
instance ILGenerator통해 MSIL 출력을 생성하는 방법을 보여 줍니다.
using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
Type^ BuildMyType()
{
AppDomain^ myDomain = Thread::GetDomain();
AssemblyName^ myAsmName = gcnew AssemblyName;
myAsmName->Name = "MyDynamicAssembly";
AssemblyBuilder^ myAsmBuilder = myDomain->DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess::Run );
ModuleBuilder^ myModBuilder = myAsmBuilder->DefineDynamicModule( "MyJumpTableDemo" );
TypeBuilder^ myTypeBuilder = myModBuilder->DefineType( "JumpTableDemo", TypeAttributes::Public );
array<Type^>^temp0 = {int::typeid};
MethodBuilder^ myMthdBuilder = myTypeBuilder->DefineMethod( "SwitchMe", static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static), String::typeid, temp0 );
ILGenerator^ myIL = myMthdBuilder->GetILGenerator();
Label defaultCase = myIL->DefineLabel();
Label endOfMethod = myIL->DefineLabel();
// We are initializing our jump table. Note that the labels
// will be placed later using the MarkLabel method.
array<Label>^jumpTable = gcnew array<Label>(5);
jumpTable[ 0 ] = myIL->DefineLabel();
jumpTable[ 1 ] = myIL->DefineLabel();
jumpTable[ 2 ] = myIL->DefineLabel();
jumpTable[ 3 ] = myIL->DefineLabel();
jumpTable[ 4 ] = myIL->DefineLabel();
// arg0, the number we passed, is pushed onto the stack.
// In this case, due to the design of the code sample,
// the value pushed onto the stack happens to match the
// index of the label (in IL terms, the index of the offset
// in the jump table). If this is not the case, such as
// when switching based on non-integer values, rules for the correspondence
// between the possible case values and each index of the offsets
// must be established outside of the ILGenerator::Emit calls,
// much as a compiler would.
myIL->Emit( OpCodes::Ldarg_0 );
myIL->Emit( OpCodes::Switch, jumpTable );
// Branch on default case
myIL->Emit( OpCodes::Br_S, defaultCase );
// Case arg0 = 0
myIL->MarkLabel( jumpTable[ 0 ] );
myIL->Emit( OpCodes::Ldstr, "are no bananas" );
myIL->Emit( OpCodes::Br_S, endOfMethod );
// Case arg0 = 1
myIL->MarkLabel( jumpTable[ 1 ] );
myIL->Emit( OpCodes::Ldstr, "is one banana" );
myIL->Emit( OpCodes::Br_S, endOfMethod );
// Case arg0 = 2
myIL->MarkLabel( jumpTable[ 2 ] );
myIL->Emit( OpCodes::Ldstr, "are two bananas" );
myIL->Emit( OpCodes::Br_S, endOfMethod );
// Case arg0 = 3
myIL->MarkLabel( jumpTable[ 3 ] );
myIL->Emit( OpCodes::Ldstr, "are three bananas" );
myIL->Emit( OpCodes::Br_S, endOfMethod );
// Case arg0 = 4
myIL->MarkLabel( jumpTable[ 4 ] );
myIL->Emit( OpCodes::Ldstr, "are four bananas" );
myIL->Emit( OpCodes::Br_S, endOfMethod );
// Default case
myIL->MarkLabel( defaultCase );
myIL->Emit( OpCodes::Ldstr, "are many bananas" );
myIL->MarkLabel( endOfMethod );
myIL->Emit( OpCodes::Ret );
return myTypeBuilder->CreateType();
}
int main()
{
Type^ myType = BuildMyType();
Console::Write( "Enter an integer between 0 and 5: " );
int theValue = Convert::ToInt32( Console::ReadLine() );
Console::WriteLine( "---" );
Object^ myInstance = Activator::CreateInstance( myType, gcnew array<Object^>(0) );
array<Object^>^temp1 = {theValue};
Console::WriteLine( "Yes, there {0} today!", myType->InvokeMember( "SwitchMe", BindingFlags::InvokeMethod, nullptr, myInstance, temp1 ) );
}
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
class DynamicJumpTableDemo
{
public static Type BuildMyType()
{
AppDomain myDomain = Thread.GetDomain();
AssemblyName myAsmName = new AssemblyName();
myAsmName.Name = "MyDynamicAssembly";
AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
myAsmName,
AssemblyBuilderAccess.Run);
ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
"MyJumpTableDemo");
TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
TypeAttributes.Public);
MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
MethodAttributes.Public |
MethodAttributes.Static,
typeof(string),
new Type[] {typeof(int)});
ILGenerator myIL = myMthdBuilder.GetILGenerator();
Label defaultCase = myIL.DefineLabel();
Label endOfMethod = myIL.DefineLabel();
// We are initializing our jump table. Note that the labels
// will be placed later using the MarkLabel method.
Label[] jumpTable = new Label[] { myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel() };
// arg0, the number we passed, is pushed onto the stack.
// In this case, due to the design of the code sample,
// the value pushed onto the stack happens to match the
// index of the label (in IL terms, the index of the offset
// in the jump table). If this is not the case, such as
// when switching based on non-integer values, rules for the correspondence
// between the possible case values and each index of the offsets
// must be established outside of the ILGenerator.Emit calls,
// much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0);
myIL.Emit(OpCodes.Switch, jumpTable);
// Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase);
// Case arg0 = 0
myIL.MarkLabel(jumpTable[0]);
myIL.Emit(OpCodes.Ldstr, "are no bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 1
myIL.MarkLabel(jumpTable[1]);
myIL.Emit(OpCodes.Ldstr, "is one banana");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 2
myIL.MarkLabel(jumpTable[2]);
myIL.Emit(OpCodes.Ldstr, "are two bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 3
myIL.MarkLabel(jumpTable[3]);
myIL.Emit(OpCodes.Ldstr, "are three bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Case arg0 = 4
myIL.MarkLabel(jumpTable[4]);
myIL.Emit(OpCodes.Ldstr, "are four bananas");
myIL.Emit(OpCodes.Br_S, endOfMethod);
// Default case
myIL.MarkLabel(defaultCase);
myIL.Emit(OpCodes.Ldstr, "are many bananas");
myIL.MarkLabel(endOfMethod);
myIL.Emit(OpCodes.Ret);
return myTypeBuilder.CreateType();
}
public static void Main()
{
Type myType = BuildMyType();
Console.Write("Enter an integer between 0 and 5: ");
int theValue = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("---");
Object myInstance = Activator.CreateInstance(myType, new object[0]);
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
BindingFlags.InvokeMethod,
null,
myInstance,
new object[] {theValue}));
}
}
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
_
Class DynamicJumpTableDemo
Public Shared Function BuildMyType() As Type
Dim myDomain As AppDomain = Thread.GetDomain()
Dim myAsmName As New AssemblyName()
myAsmName.Name = "MyDynamicAssembly"
Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.Run)
Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
TypeAttributes.Public)
Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
MethodAttributes.Public Or MethodAttributes.Static, _
GetType(String), New Type() {GetType(Integer)})
Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
Dim defaultCase As Label = myIL.DefineLabel()
Dim endOfMethod As Label = myIL.DefineLabel()
' We are initializing our jump table. Note that the labels
' will be placed later using the MarkLabel method.
Dim jumpTable() As Label = {myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel()}
' arg0, the number we passed, is pushed onto the stack.
' In this case, due to the design of the code sample,
' the value pushed onto the stack happens to match the
' index of the label (in IL terms, the index of the offset
' in the jump table). If this is not the case, such as
' when switching based on non-integer values, rules for the correspondence
' between the possible case values and each index of the offsets
' must be established outside of the ILGenerator.Emit calls,
' much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0)
myIL.Emit(OpCodes.Switch, jumpTable)
' Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase)
' Case arg0 = 0
myIL.MarkLabel(jumpTable(0))
myIL.Emit(OpCodes.Ldstr, "are no bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 1
myIL.MarkLabel(jumpTable(1))
myIL.Emit(OpCodes.Ldstr, "is one banana")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 2
myIL.MarkLabel(jumpTable(2))
myIL.Emit(OpCodes.Ldstr, "are two bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 3
myIL.MarkLabel(jumpTable(3))
myIL.Emit(OpCodes.Ldstr, "are three bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 4
myIL.MarkLabel(jumpTable(4))
myIL.Emit(OpCodes.Ldstr, "are four bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Default case
myIL.MarkLabel(defaultCase)
myIL.Emit(OpCodes.Ldstr, "are many bananas")
myIL.MarkLabel(endOfMethod)
myIL.Emit(OpCodes.Ret)
Return myTypeBuilder.CreateType()
End Function 'BuildMyType
Public Shared Sub Main()
Dim myType As Type = BuildMyType()
Console.Write("Enter an integer between 0 and 5: ")
Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
Console.WriteLine("---")
Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
BindingFlags.InvokeMethod, Nothing, _
myInstance, New Object() {theValue}))
End Sub
End Class
설명
매개 변수에 opcode
인수가 필요한 경우 호출자는 인수 길이가 선언된 매개 변수의 길이와 일치하는지 확인해야 합니다. 그렇지 않으면 결과를 예측할 수 없습니다. 예를 들어 내보내기 명령에 2바이트 피연산자가 필요하고 호출자가 4바이트 피연산자를 제공하는 경우 런타임은 명령 스트림에 두 개의 추가 바이트를 내보낸다. 이러한 추가 바이트는 지침입니다 Nop .
명령 값은 에 정의되어 있습니다 OpCodes.
적용 대상
Emit(OpCode, Label)
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
- Source:
- ILGenerator.cs
지정된 명령을 MSIL(Microsoft Intermediate Language) 스트림에 배치하고 고정이 완료되면 레이블을 포함할 공간을 남겨 둡니다.
public:
virtual void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::Label label);
public:
abstract void Emit(System::Reflection::Emit::OpCode opcode, System::Reflection::Emit::Label label);
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
override this.Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
abstract member Emit : System.Reflection.Emit.OpCode * System.Reflection.Emit.Label -> unit
Public Overridable Sub Emit (opcode As OpCode, label As Label)
Public MustOverride Sub Emit (opcode As OpCode, label As Label)
매개 변수
- opcode
- OpCode
스트림에 내보낼 MSIL 명령입니다.
- label
- Label
이 위치에서 분기될 레이블입니다.
예제
아래 코드 샘플에서는 점프 테이블을 사용하여 동적 메서드를 만드는 방법을 보여 줍니다. 점프 테이블은 배열 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.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
설명
명령 값은 열거형에 OpCodes
정의됩니다.
레이블은 를 사용하여 DefineLabel만들어지고 스트림 내의 위치는 를 사용하여 MarkLabel수정됩니다. 단일 바이트 명령이 사용되는 경우 레이블은 스트림을 따라 최대 127바이트의 점프를 나타낼 수 있습니다.
opcode
는 분기 명령을 나타내야 합니다. 분기는 상대 지침 label
이므로 는 수정 프로세스 중에 분기에 대한 올바른 오프셋으로 바뀝니다.
적용 대상
.NET