Export (0) Print
Expand All

OpCodes Class

Provides field representations of the Microsoft Intermediate Language (MSIL) instructions for emission by the ILGenerator class members (such as Emit).

For a list of all members of this type, see OpCodes Members.

System.Object
   System.Reflection.Emit.OpCodes

[Visual Basic]
Public Class OpCodes
[C#]
public class OpCodes
[C++]
public __gc class OpCodes
[JScript]
public class OpCodes

Thread Safety

Reflection Emit is thread-safe when using assemblies that were created with the AppDomain.DefineDynamicAssembly method with the Boolean parameter isSynchronized set to true.

Remarks

See the Common Language Infrastructure Instruction Set documentation in the Tool Developers Guide for a detailed description of the member opcodes.

Example

[Visual Basic, C#, C++] The following example demonstrates the construction of a dynamic method using ILGenerator to emit OpCodes into a MethodBuilder.

[Visual Basic] 

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

 _

Class EmitWriteLineDemo
   
   
   Public Shared Function CreateDynamicType() As Type

      Dim ctorParams() As Type = {GetType(Integer), GetType(Integer)}
      
      Dim myDomain As AppDomain = Thread.GetDomain()
      Dim myAsmName As New AssemblyName()
      myAsmName.Name = "MyDynamicAssembly"
      
      Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.RunAndSave)
      
      Dim pointModule As ModuleBuilder = myAsmBuilder.DefineDynamicModule("PointModule", "Point.dll")
      
      Dim pointTypeBld As TypeBuilder = pointModule.DefineType("Point", _
                                   TypeAttributes.Public)
      
      Dim xField As FieldBuilder = pointTypeBld.DefineField("x", _
                                GetType(Integer), _
                                FieldAttributes.Public)
      Dim yField As FieldBuilder = pointTypeBld.DefineField("y", _
                                GetType(Integer), _
                                 FieldAttributes.Public)
      
      
      Dim objType As Type = Type.GetType("System.Object")
      Dim objCtor As ConstructorInfo = objType.GetConstructor(New Type(){})
      
      Dim pointCtor As ConstructorBuilder = pointTypeBld.DefineConstructor( _
                             MethodAttributes.Public, _
                             CallingConventions.Standard, _
                             ctorParams)
      Dim ctorIL As ILGenerator = pointCtor.GetILGenerator()
      
      
      ' First, you build the constructor.

      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Call, objCtor)
      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Ldarg_1)
      ctorIL.Emit(OpCodes.Stfld, xField)
      ctorIL.Emit(OpCodes.Ldarg_0)
      ctorIL.Emit(OpCodes.Ldarg_2)
      ctorIL.Emit(OpCodes.Stfld, yField)
      ctorIL.Emit(OpCodes.Ret)
      
      '  Now, you'll build a method to output some information on the
      ' inside your dynamic class. This method will have the following
      ' definition in C#:
      '  Public Sub WritePoint() 

      Dim writeStrMthd As MethodBuilder = pointTypeBld.DefineMethod("WritePoint", _
                                    MethodAttributes.Public, _
                                    Nothing, Nothing)
      
      Dim writeStrIL As ILGenerator = writeStrMthd.GetILGenerator()
      
      ' The below ILGenerator created demonstrates a few ways to create
      ' string output through STDIN. 
      ' ILGenerator.EmitWriteLine(string) will generate a ldstr and a 
      ' call to WriteLine for you.

      writeStrIL.EmitWriteLine("The value of this current instance is:")
      
      ' Here, you will do the hard work yourself. First, you need to create
      ' the string we will be passing and obtain the correct WriteLine overload
      ' for said string. In the below case, you are substituting in two values,
      ' so the chosen overload is Console.WriteLine(string, object, object).

      Dim inStr As [String] = "({0}, {1})"
      Dim wlParams() As Type = {GetType(String), GetType(Object), GetType(Object)}
      
      ' We need the MethodInfo to pass into EmitCall later.

      Dim writeLineMI As MethodInfo = GetType(Console).GetMethod("WriteLine", wlParams)
      
      ' Push the string with the substitutions onto the stack.
      ' This is the first argument for WriteLine - the string one. 

      writeStrIL.Emit(OpCodes.Ldstr, inStr)
      
      ' Since the second argument is an object, and it corresponds to
      ' to the substitution for the value of our integer field, you 
      ' need to box that field to an object. First, push a reference
      ' to the current instance, and then push the value stored in
      ' field 'x'. We need the reference to the current instance (stored
      ' in local argument index 0) so Ldfld can load from the correct
      ' instance (this one).

      writeStrIL.Emit(OpCodes.Ldarg_0)
      writeStrIL.Emit(OpCodes.Ldfld, xField)
      
      ' Now, we execute the box opcode, which pops the value of field 'x',
      ' returning a reference to the integer value boxed as an object.

      writeStrIL.Emit(OpCodes.Box, GetType(Integer))
      
      ' Atop the stack, you'll find our string inStr, followed by a reference
      ' to the boxed value of 'x'. Now, you need to likewise box field 'y'.

      writeStrIL.Emit(OpCodes.Ldarg_0)
      writeStrIL.Emit(OpCodes.Ldfld, yField)
      writeStrIL.Emit(OpCodes.Box, GetType(Integer))
      
      ' Now, you have all of the arguments for your call to
      ' Console.WriteLine(string, object, object) atop the stack:
      ' the string InStr, a reference to the boxed value of 'x', and
      ' a reference to the boxed value of 'y'.
      ' Call Console.WriteLine(string, object, object) with EmitCall.

      writeStrIL.EmitCall(OpCodes.Call, writeLineMI, Nothing)
      
      ' Lastly, EmitWriteLine can also output the value of a field
      ' using the overload EmitWriteLine(FieldInfo).

      writeStrIL.EmitWriteLine("The value of 'x' is:")
      writeStrIL.EmitWriteLine(xField)
      writeStrIL.EmitWriteLine("The value of 'y' is:")
      writeStrIL.EmitWriteLine(yField)
      
      ' Since we return no value (void), the the ret opcode will not
      ' return the top stack value.

      writeStrIL.Emit(OpCodes.Ret)
      
      Return pointTypeBld.CreateType()

   End Function 'CreateDynamicType
    
   
   Public Shared Sub Main()
      
      Dim ctorParams(1) As Object
      
      Console.Write("Enter a integer value for X: ")
      Dim myX As String = Console.ReadLine()
      Console.Write("Enter a integer value for Y: ")
      Dim myY As String = Console.ReadLine()
      
      Console.WriteLine("---")
      
      ctorParams(0) = Convert.ToInt32(myX)
      ctorParams(1) = Convert.ToInt32(myY)
      
      Dim ptType As Type = CreateDynamicType()

      Dim ptInstance As Object = Activator.CreateInstance(ptType, ctorParams)

      ptType.InvokeMember("WritePoint", _
              BindingFlags.InvokeMethod, _
              Nothing, ptInstance, Nothing)

   End Sub 'Main

End Class 'EmitWriteLineDemo


[C#] 

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

class EmitWriteLineDemo {

   public static Type CreateDynamicType() {       
       Type[] ctorParams = new Type[] {typeof(int),
                   typeof(int)};
     
       AppDomain myDomain = Thread.GetDomain();
       AssemblyName myAsmName = new AssemblyName();
       myAsmName.Name = "MyDynamicAssembly";

       AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                      myAsmName, 
                      AssemblyBuilderAccess.RunAndSave);

       ModuleBuilder pointModule = myAsmBuilder.DefineDynamicModule("PointModule",
                                    "Point.dll");

       TypeBuilder pointTypeBld = pointModule.DefineType("Point",
                                  TypeAttributes.Public);

       FieldBuilder xField = pointTypeBld.DefineField("x", typeof(int),
                                                      FieldAttributes.Public);
       FieldBuilder yField = pointTypeBld.DefineField("y", typeof(int), 
                                                      FieldAttributes.Public);


       Type objType = Type.GetType("System.Object"); 
       ConstructorInfo objCtor = objType.GetConstructor(new Type[0]);

       ConstructorBuilder pointCtor = pointTypeBld.DefineConstructor(
                                    MethodAttributes.Public,
                                   CallingConventions.Standard,
                                   ctorParams);
       ILGenerator ctorIL = pointCtor.GetILGenerator();


       // First, you build the constructor.
       ctorIL.Emit(OpCodes.Ldarg_0);
       ctorIL.Emit(OpCodes.Call, objCtor);
       ctorIL.Emit(OpCodes.Ldarg_0);
       ctorIL.Emit(OpCodes.Ldarg_1);
       ctorIL.Emit(OpCodes.Stfld, xField); 
       ctorIL.Emit(OpCodes.Ldarg_0);
       ctorIL.Emit(OpCodes.Ldarg_2);
       ctorIL.Emit(OpCodes.Stfld, yField); 
       ctorIL.Emit(OpCodes.Ret); 

       //  Now, you'll build a method to output some information on the
       // inside your dynamic class. This method will have the following
       // definition in C#:
    //  public void WritePoint()
      
       MethodBuilder writeStrMthd = pointTypeBld.DefineMethod(
                                     "WritePoint", 
                             MethodAttributes.Public,
                                             typeof(void), 
                                             null);

       
       ILGenerator writeStrIL = writeStrMthd.GetILGenerator();
      
       // The below ILGenerator created demonstrates a few ways to create
       // string output through STDIN. 

       // ILGenerator.EmitWriteLine(string) will generate a ldstr and a 
       // call to WriteLine for you.

       writeStrIL.EmitWriteLine("The value of this current instance is:");

       // Here, you will do the hard work yourself. First, you need to create
       // the string we will be passing and obtain the correct WriteLine overload
       // for said string. In the below case, you are substituting in two values,
       // so the chosen overload is Console.WriteLine(string, object, object).

       String inStr = "({0}, {1})";
       Type[] wlParams = new Type[] {typeof(string),
                     typeof(object),
                     typeof(object)};

       // We need the MethodInfo to pass into EmitCall later.

       MethodInfo writeLineMI = typeof(Console).GetMethod(
                            "WriteLine",
                        wlParams);

       // Push the string with the substitutions onto the stack.
       // This is the first argument for WriteLine - the string one. 

       writeStrIL.Emit(OpCodes.Ldstr, inStr);

       // Since the second argument is an object, and it corresponds to
       // to the substitution for the value of our integer field, you 
       // need to box that field to an object. First, push a reference
       // to the current instance, and then push the value stored in
       // field 'x'. We need the reference to the current instance (stored
       // in local argument index 0) so Ldfld can load from the correct
       // instance (this one).

       writeStrIL.Emit(OpCodes.Ldarg_0);
       writeStrIL.Emit(OpCodes.Ldfld, xField);

       // Now, we execute the box opcode, which pops the value of field 'x',
       // returning a reference to the integer value boxed as an object.

       writeStrIL.Emit(OpCodes.Box, typeof(int));

       // Atop the stack, you'll find our string inStr, followed by a reference
       // to the boxed value of 'x'. Now, you need to likewise box field 'y'.

       writeStrIL.Emit(OpCodes.Ldarg_0);
       writeStrIL.Emit(OpCodes.Ldfld, yField);
       writeStrIL.Emit(OpCodes.Box, typeof(int));

       // Now, you have all of the arguments for your call to
       // Console.WriteLine(string, object, object) atop the stack:
       // the string InStr, a reference to the boxed value of 'x', and
       // a reference to the boxed value of 'y'.

       // Call Console.WriteLine(string, object, object) with EmitCall.

       writeStrIL.EmitCall(OpCodes.Call, writeLineMI, null);

       // Lastly, EmitWriteLine can also output the value of a field
       // using the overload EmitWriteLine(FieldInfo).

       writeStrIL.EmitWriteLine("The value of 'x' is:");
       writeStrIL.EmitWriteLine(xField);
       writeStrIL.EmitWriteLine("The value of 'y' is:");
       writeStrIL.EmitWriteLine(yField);

       // Since we return no value (void), the the ret opcode will not
       // return the top stack value.

       writeStrIL.Emit(OpCodes.Ret);
      
       return pointTypeBld.CreateType();

   }

   public static void Main() {

      object[] ctorParams = new object[2];

      Console.Write("Enter a integer value for X: "); 
      string myX = Console.ReadLine();
      Console.Write("Enter a integer value for Y: "); 
      string myY = Console.ReadLine();

      Console.WriteLine("---");

      ctorParams[0] = Convert.ToInt32(myX);
      ctorParams[1] = Convert.ToInt32(myY);

      Type ptType = CreateDynamicType();
  
      object ptInstance = Activator.CreateInstance(ptType, ctorParams);
      ptType.InvokeMember("WritePoint",
              BindingFlags.InvokeMethod,
              null,
              ptInstance,
              new object[0]);
   }
}


[C++] 
#using <mscorlib.dll>

using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;

Type* CreateDynamicType() {
   Type* ctorParams[] = {__typeof(int),
      __typeof(int)};

   AppDomain*  myDomain = Thread::GetDomain();
   AssemblyName* myAsmName = new AssemblyName();
   myAsmName->Name = S"MyDynamicAssembly";

   AssemblyBuilder*  myAsmBuilder = myDomain->DefineDynamicAssembly(myAsmName,
      AssemblyBuilderAccess::RunAndSave);

   ModuleBuilder*  pointModule = myAsmBuilder->DefineDynamicModule(S"PointModule",
      S"Point.dll");

   TypeBuilder*  pointTypeBld = pointModule->DefineType(S"Point",
      TypeAttributes::Public);

   FieldBuilder*  xField = pointTypeBld->DefineField(S"x", __typeof(int),
      FieldAttributes::Public);
   FieldBuilder*  yField = pointTypeBld->DefineField(S"y", __typeof(int),
      FieldAttributes::Public);

   Type*  objType = Type::GetType(S"System.Object");
   ConstructorInfo*  objCtor = objType->GetConstructor(new Type*[0]);

   ConstructorBuilder*  pointCtor = pointTypeBld->DefineConstructor(MethodAttributes::Public,
      CallingConventions::Standard,
      ctorParams);
   ILGenerator*  ctorIL = pointCtor->GetILGenerator();

   // First, you build the constructor.
   ctorIL->Emit(OpCodes::Ldarg_0);
   ctorIL->Emit(OpCodes::Call, objCtor);
   ctorIL->Emit(OpCodes::Ldarg_0);
   ctorIL->Emit(OpCodes::Ldarg_1);
   ctorIL->Emit(OpCodes::Stfld, xField);
   ctorIL->Emit(OpCodes::Ldarg_0);
   ctorIL->Emit(OpCodes::Ldarg_2);
   ctorIL->Emit(OpCodes::Stfld, yField);
   ctorIL->Emit(OpCodes::Ret);

   //  Now, you'll build a method to output some information on the
   // inside your dynamic class. This method will have the following
   // definition in C#:
   //  public void WritePoint()

   MethodBuilder*  writeStrMthd = pointTypeBld->DefineMethod(S"WritePoint",
      MethodAttributes::Public,
      __typeof(void),
      0);

   ILGenerator*  writeStrIL = writeStrMthd->GetILGenerator();

   // The below ILGenerator created demonstrates a few ways to create
   // String* output through STDIN.

   // ILGenerator::EmitWriteLine(String*) will generate a ldstr and a
   // call to WriteLine for you.

   writeStrIL->EmitWriteLine(S"The value of this current instance is:");

   // Here, you will do the hard work yourself. First, you need to create
   // the String* we will be passing and obtain the correct WriteLine overload
   // for said String*. In the below case, you are substituting in two values,
   // so the chosen overload is Console::WriteLine(String*, Object*, Object*).

   String*  inStr = S"( {0}, {1})";
   Type* wlParams[] = {__typeof(String),
      __typeof(Object),
      __typeof(Object)};

   // We need the MethodInfo to pass into EmitCall later.

   MethodInfo*  writeLineMI = __typeof(Console)->GetMethod(S"WriteLine",
      wlParams);

   // Push the String* with the substitutions onto the stack.
   // This is the first argument for WriteLine - the String* one.

   writeStrIL->Emit(OpCodes::Ldstr, inStr);

   // Since the second argument is an Object*, and it corresponds to
   // to the substitution for the value of our integer field, you
   // need to box that field to an Object*. First, push a reference
   // to the current instance, and then push the value stored in
   // field 'x'. We need the reference to the current instance (stored
   // in local argument index 0) so Ldfld can load from the correct
   // instance (this one).

   writeStrIL->Emit(OpCodes::Ldarg_0);
   writeStrIL->Emit(OpCodes::Ldfld, xField);

   // Now, we execute the box opcode, which pops the value of field 'x',
   // returning a reference to the integer value boxed as an Object*.

   writeStrIL->Emit(OpCodes::Box, __typeof(int));

   // Atop the stack, you'll find our String* inStr, followed by a reference
   // to the boxed value of 'x'. Now, you need to likewise box field 'y'.

   writeStrIL->Emit(OpCodes::Ldarg_0);
   writeStrIL->Emit(OpCodes::Ldfld, yField);
   writeStrIL->Emit(OpCodes::Box, __typeof(int));

   // Now, you have all of the arguments for your call to
   // Console::WriteLine(String*, Object*, Object*) atop the stack:
   // the String* InStr, a reference to the boxed value of 'x', and
   // a reference to the boxed value of 'y'.

   // Call Console::WriteLine(String*, Object*, Object*) with EmitCall.

   writeStrIL->EmitCall(OpCodes::Call, writeLineMI, 0);

   // Lastly, EmitWriteLine can also output the value of a field
   // using the overload EmitWriteLine(FieldInfo).

   writeStrIL->EmitWriteLine(S"The value of 'x' is:");
   writeStrIL->EmitWriteLine(xField);
   writeStrIL->EmitWriteLine(S"The value of 'y' is:");
   writeStrIL->EmitWriteLine(yField);

   // Since we return no value (void), the the ret opcode will not
   // return the top stack value.

   writeStrIL->Emit(OpCodes::Ret);

   return pointTypeBld->CreateType();
}

int main() {

   Object* ctorParams[] = new Object*[2];

   Console::Write(S"Enter a integer value for X: ");
   String* myX = Console::ReadLine();
   Console::Write(S"Enter a integer value for Y: ");
   String* myY = Console::ReadLine();

   Console::WriteLine(S"---");

   ctorParams[0] = __box(Convert::ToInt32(myX));
   ctorParams[1] = __box(Convert::ToInt32(myY));

   Type*  ptType = CreateDynamicType();

   Object* ptInstance = Activator::CreateInstance(ptType, ctorParams);
   ptType->InvokeMember(S"WritePoint",
      BindingFlags::InvokeMethod,
      0,
      ptInstance,
      new Object*[0]);
}

[JScript] No example is available for JScript. To view a Visual Basic, C#, or C++ example, click the Language Filter button Language Filter in the upper-left corner of the page.

Requirements

Namespace: System.Reflection.Emit

Platforms: Windows 98, Windows NT 4.0, Windows Millennium Edition, Windows 2000, Windows XP Home Edition, Windows XP Professional, Windows Server 2003 family

Assembly: Mscorlib (in Mscorlib.dll)

See Also

OpCodes Members | System.Reflection.Emit Namespace

Show:
© 2014 Microsoft