ILGenerator.Emit Method (OpCode, array<Label[])
Microsoft Silverlight will reach end of support after October 2021. Learn more.
Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.
Namespace: System.Reflection.Emit
Assembly: mscorlib (in mscorlib.dll)
Syntax
'Declaration
Public Overridable Sub Emit ( _
opcode As OpCode, _
labels As Label() _
)
public virtual void Emit(
OpCode opcode,
Label[] labels
)
Parameters
- opcode
Type: System.Reflection.Emit.OpCode
The MSIL instruction to be emitted onto the stream.
- labels
Type: array<System.Reflection.Emit.Label[]
The array of label objects that forms the jump table.
Exceptions
Exception | Condition |
---|---|
ArgumentNullException | labels is nulla null reference (Nothing in Visual Basic). |
Remarks
This method overload emits a switch table.
The instruction values are defined in the OpCodes enumeration.
Labels are created by using the DefineLabel method, and their location within the stream is fixed by using the MarkLabel method. If a single-byte instruction is used, each label can represent a jump of at most 127 bytes along the stream. opcode must represent a branch instruction. Because branches are relative instructions, during the fixup process each label will be replaced with the correct offset to branch to.
Examples
The code sample below illustrates the creation of a dynamic method with a jump table. The jump table is built using an array of Label.
Note: |
---|
To run this example, see Building Examples That Use a Demo Method and a TextBlock Control. |
Imports System.Reflection
Imports System.Reflection.Emit
Class Example
Public Shared Sub Demo(ByVal outputBlock As System.Windows.Controls.TextBlock)
Dim myDomain As AppDomain = AppDomain.CurrentDomain
Dim myAsmName As New AssemblyName("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()
' Initialize the 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 method argument, 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)
Dim myType As Type = myTypeBuilder.CreateType()
Dim testValues() As Integer = { 3, 500, 0 }
Dim obj As Object = Activator.CreateInstance(myType)
For Each testValue As Integer In testValues
Dim result As Object = _
myType.InvokeMember("SwitchMe", _
BindingFlags.InvokeMethod, _
Type.DefaultBinder, _
obj, _
New Object() { testValue })
outputBlock.Text &= String.Format("Yes, there {0} today!", result) & vbLf
Next
End Sub
End Class
' This example produces the following output:
'
'Yes, there are three bananas today!
'Yes, there are many bananas today!
'Yes, there are no bananas today!
using System;
using System.Reflection;
using System.Reflection.Emit;
class Example
{
public static void Demo(System.Windows.Controls.TextBlock outputBlock)
{
AppDomain myDomain = AppDomain.CurrentDomain;
AssemblyName myAsmName = new AssemblyName("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();
// Initialize the jump table. Note that the labels
// will be placed later using the MarkLabel method.
Label[] jumpTable = {myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel(),
myIL.DefineLabel()};
// arg0, the method argument, 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);
Type myType = myTypeBuilder.CreateType();
int[] testValues = {3, 500, 0};
object obj = Activator.CreateInstance(myType);
foreach( int testValue in testValues )
{
object result =
myType.InvokeMember("SwitchMe",
BindingFlags.InvokeMethod,
Type.DefaultBinder,
obj,
new object[] { testValue });
outputBlock.Text += String.Format("Yes, there {0} today!\n", result);
}
}
}
/* This example produces the following output:
Yes, there are three bananas today!
Yes, there are many bananas today!
Yes, there are no bananas today!
*/
Version Information
Silverlight
Supported in: 5, 4, 3
Silverlight for Windows Phone
Supported in: Windows Phone OS 7.1
Platforms
For a list of the operating systems and browsers that are supported by Silverlight, see Supported Operating Systems and Browsers.