指定された命令を命令のストリームに書き込みます。
Overloads Public Overridable Sub Emit( _
ByVal opcode As OpCode _)
[C#]
public virtual void Emit(OpCodeopcode);
[C++]
public: virtual void Emit(OpCodeopcode);
[JScript]
public function Emit(
opcode : OpCode);
パラメータ
- opcode
ストリームに書き込む MSIL (Microsoft Intermediate Language) 命令。
解説
オペコードに引数が必要な場合は、呼び出し元で、引数の長さが宣言されたパラメータの長さと一致することを確認する必要があります。確認しない場合、結果は予測できません。たとえば、Emit 命令に 2 バイトのオペランドが必要で、呼び出し元が 4 バイトのオペランドを渡した場合、Runtime は命令ストリームに追加の 2 バイトを提供します。この追加されたバイトは、 Nop 命令になります。この命令値は、 OpCodes で定義されます。
使用例
[Visual Basic, C#, C++] Emit を使用し、 ILGenerator のインスタンスを通じて MSIL 出力を生成する方法を次のコード例に示します。
Imports System
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit
_
Class DynamicJumpTableDemo
Public Shared Function BuildMyType() As Type
Dim myDomain As AppDomain = Thread.GetDomain()
Dim myAsmName As New AssemblyName()
myAsmName.Name = "MyDynamicAssembly"
Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
AssemblyBuilderAccess.Run)
Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
TypeAttributes.Public)
Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
MethodAttributes.Public Or MethodAttributes.Static, _
GetType(String), New Type() {GetType(Integer)})
Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
Dim defaultCase As Label = myIL.DefineLabel()
Dim endOfMethod As Label = myIL.DefineLabel()
' We are initializing our jump table. Note that the labels
' will be placed later using the MarkLabel method.
Dim jumpTable() As Label = {myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel(), _
myIL.DefineLabel()}
' arg0, the number we passed, is pushed onto the stack.
' In this case, due to the design of the code sample,
' the value pushed onto the stack happens to match the
' index of the label (in IL terms, the index of the offset
' in the jump table). If this is not the case, such as
' when switching based on non-integer values, rules for the correspondence
' between the possible case values and each index of the offsets
' must be established outside of the ILGenerator.Emit calls,
' much as a compiler would.
myIL.Emit(OpCodes.Ldarg_0)
myIL.Emit(OpCodes.Switch, jumpTable)
' Branch on default case
myIL.Emit(OpCodes.Br_S, defaultCase)
' Case arg0 = 0
myIL.MarkLabel(jumpTable(0))
myIL.Emit(OpCodes.Ldstr, "are no bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 1
myIL.MarkLabel(jumpTable(1))
myIL.Emit(OpCodes.Ldstr, "is one banana")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 2
myIL.MarkLabel(jumpTable(2))
myIL.Emit(OpCodes.Ldstr, "are two bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 3
myIL.MarkLabel(jumpTable(3))
myIL.Emit(OpCodes.Ldstr, "are three bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Case arg0 = 4
myIL.MarkLabel(jumpTable(4))
myIL.Emit(OpCodes.Ldstr, "are four bananas")
myIL.Emit(OpCodes.Br_S, endOfMethod)
' Default case
myIL.MarkLabel(defaultCase)
myIL.Emit(OpCodes.Ldstr, "are many bananas")
myIL.MarkLabel(endOfMethod)
myIL.Emit(OpCodes.Ret)
Return myTypeBuilder.CreateType()
End Function 'BuildMyType
Public Shared Sub Main()
Dim myType As Type = BuildMyType()
Console.Write("Enter an integer between 0 and 5: ")
Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
Console.WriteLine("---")
Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
BindingFlags.InvokeMethod, Nothing, _
myInstance, New Object() {theValue}))
End Sub 'Main
End Class 'DynamicJumpTableDemo
[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}));
}
}
[C++]
#using <mscorlib.dll>
using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
Type* BuildMyType() {
AppDomain* myDomain = Thread::GetDomain();
AssemblyName* myAsmName = new AssemblyName();
myAsmName->Name = S"MyDynamicAssembly";
AssemblyBuilder* myAsmBuilder = myDomain->DefineDynamicAssembly(myAsmName,
AssemblyBuilderAccess::Run);
ModuleBuilder* myModBuilder = myAsmBuilder->DefineDynamicModule(S"MyJumpTableDemo");
TypeBuilder* myTypeBuilder = myModBuilder->DefineType(S"JumpTableDemo",
TypeAttributes::Public);
Type* temp0 [] = {__typeof(int)};
MethodBuilder* myMthdBuilder = myTypeBuilder->DefineMethod(
S"SwitchMe",
static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static),
__typeof(String),
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.
Label jumpTable [] = new 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, S"are no bananas");
myIL->Emit(OpCodes::Br_S, endOfMethod);
// Case arg0 = 1
myIL->MarkLabel(jumpTable[1]);
myIL->Emit(OpCodes::Ldstr, S"is one banana");
myIL->Emit(OpCodes::Br_S, endOfMethod);
// Case arg0 = 2
myIL->MarkLabel(jumpTable[2]);
myIL->Emit(OpCodes::Ldstr, S"are two bananas");
myIL->Emit(OpCodes::Br_S, endOfMethod);
// Case arg0 = 3
myIL->MarkLabel(jumpTable[3]);
myIL->Emit(OpCodes::Ldstr, S"are three bananas");
myIL->Emit(OpCodes::Br_S, endOfMethod);
// Case arg0 = 4
myIL->MarkLabel(jumpTable[4]);
myIL->Emit(OpCodes::Ldstr, S"are four bananas");
myIL->Emit(OpCodes::Br_S, endOfMethod);
// Default case
myIL->MarkLabel(defaultCase);
myIL->Emit(OpCodes::Ldstr, S"are many bananas");
myIL->MarkLabel(endOfMethod);
myIL->Emit(OpCodes::Ret);
return myTypeBuilder->CreateType();
}
int main() {
Type* myType = BuildMyType();
Console::Write(S"Enter an integer between 0 and 5: ");
int theValue = Convert::ToInt32(Console::ReadLine());
Console::WriteLine(S"---");
Object* myInstance = Activator::CreateInstance(myType, new Object*[0]);
Object* temp1 [] = {__box(theValue)};
Console::WriteLine(S"Yes, there {0} today!", myType->InvokeMember(S"SwitchMe",
BindingFlags::InvokeMethod,
0,
myInstance,
temp1));
}
[JScript] JScript のサンプルはありません。Visual Basic、C#、および C++ のサンプルを表示するには、このページの左上隅にある言語のフィルタ ボタン をクリックします。
必要条件
プラットフォーム: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 ファミリ
参照
ILGenerator クラス | ILGenerator メンバ | System.Reflection.Emit 名前空間 | ILGenerator.Emit オーバーロードの一覧