このドキュメントはアーカイブされており、メンテナンスされていません。

ILGenerator.Emit メソッド (OpCode)

指定された命令を命令のストリームに書き込みます。

名前空間: System.Reflection.Emit
アセンブリ: mscorlib (mscorlib.dll 内)

public virtual void Emit (
	OpCode opcode
)
public void Emit (
	OpCode opcode
)
public function Emit (
	opcode : OpCode
)

パラメータ

opcode

ストリームに書き込む MSIL (Microsoft Intermediate Language) 命令。

オペコードに引数が必要な場合は、呼び出し元で、引数の長さが宣言されたパラメータの長さと一致することを確認する必要があります。確認しない場合、結果は予測できません。たとえば、Emit 命令に 2 バイトのオペランドが必要で、呼び出し元が 4 バイトのオペランドを渡した場合、Runtime は命令ストリームに追加の 2 バイトを提供します。この追加されたバイトは、Nop 命令になります。

この命令値は、OpCodes で定義されます。

Emit を使用し、ILGenerator のインスタンスを通じて MSIL 出力を生成する方法を次のコード例に示します。


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

}


import System .* ;
import System.Threading .* ;
import System.Reflection .* ;
import System.Reflection.Emit .* ;

class DynamicJumpTableDemo
{
    public static Type BuildMyType()
    {
        AppDomain myDomain = System.Threading.Thread.GetDomain();
        AssemblyName myAsmName = new AssemblyName();
        myAsmName.set_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,
            String.class.ToType(),new Type[] { int.class.ToType() });
        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();
    } //BuildMyType    
   
   public static void main(String[] args)
   {
        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[]{(Int32)(theValue)}));
    } //main
} //DynamicJumpTableDemo

Windows 98, Windows 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition

開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。

.NET Framework

サポート対象 : 2.0、1.1、1.0
表示: