C # - 5395
Pozwala emitować kod cil do dodania przy użyciu metody dynamicznej. Właściwie emituję kod, który z kolei emituje kod w celu wywołania dodania liczby całkowitej. Poniższa funkcja Add()
buduje metodę dynamiczną, która po uruchomieniu tworzy metodę dynamiczną do wywoływania dodawania liczb całkowitych.
using System;
using System.Reflection.Emit;
namespace JA
{
class Program
{
static void Main(string[] args)
{
int z=Add(1, 2);
// z = 3
}
// Emit MSIL to emit MSIL
public static int Add(int x, int y)
{
Type delegate_type=typeof(Func<int, int, int>);
DynamicMethod method=new DynamicMethod(typeof(int).ToString()+".op_Addition",
typeof(int),
new Type[] { typeof(int), typeof(int) }, typeof(Program));
ILGenerator generator=method.GetILGenerator();
LocalBuilder method1=generator.DeclareLocal(typeof(DynamicMethod));
LocalBuilder generator1=generator.DeclareLocal(typeof(ILGenerator));
LocalBuilder add1=generator.DeclareLocal(typeof(Func<int, int, int>));
LocalBuilder args1=generator.DeclareLocal(typeof(Type[]));
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(object).GetMethod("ToString",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Instance));
generator.Emit(OpCodes.Ldstr, ".op_Addition");
generator.Emit(OpCodes.Call,
typeof(string).GetMethod("Concat",
new Type[] { typeof(string), typeof(string) }));
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Ldc_I4, 2);
generator.Emit(OpCodes.Newarr, typeof(Type));
generator.Emit(OpCodes.Stloc_3);
generator.Emit(OpCodes.Ldloc_3);
generator.Emit(OpCodes.Ldc_I4, 0);
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Stelem_Ref);
generator.Emit(OpCodes.Ldloc_3);
generator.Emit(OpCodes.Ldc_I4, 1);
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Stelem_Ref);
generator.Emit(OpCodes.Ldloc_3);
generator.Emit(OpCodes.Ldtoken, typeof(Program));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Newobj,
typeof(DynamicMethod).GetConstructor(
new Type[] { typeof(string), typeof(Type), typeof(Type[]), typeof(Type) }));
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Callvirt,
typeof(DynamicMethod).GetMethod("GetILGenerator",
Type.EmptyTypes));
generator.Emit(OpCodes.Stloc_1);
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldtoken, typeof(int));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("DeclareLocal",
new Type[] { typeof(Type) }));
generator.Emit(OpCodes.Pop);
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ldarg_0",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ldarg_1",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Add",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Stloc_0",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ldloc_0",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_1);
generator.Emit(OpCodes.Ldsfld,
typeof(OpCodes).GetField("Ret",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(ILGenerator).GetMethod("Emit", new Type[] { typeof(OpCode) }));
generator.Emit(OpCodes.Ldloc_0);
generator.Emit(OpCodes.Ldtoken, typeof(Func<int, int, int>));
generator.Emit(OpCodes.Call,
typeof(Type).GetMethod("GetTypeFromHandle",
System.Reflection.BindingFlags.Public|
System.Reflection.BindingFlags.Static));
generator.Emit(OpCodes.Callvirt,
typeof(DynamicMethod).GetMethod("CreateDelegate",
new Type[] { typeof(Type) }));
generator.Emit(OpCodes.Isinst, typeof(Func<int, int, int>));
generator.Emit(OpCodes.Stloc_2);
generator.Emit(OpCodes.Ldloc_2);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Callvirt,
typeof(Func<int, int, int>).GetMethod("Invoke",
System.Reflection.BindingFlags.Public|System.Reflection.BindingFlags.Instance));
generator.Emit(OpCodes.Ret);
Func<int, int, int> add2=method.CreateDelegate(typeof(Func<int, int, int>)) as Func<int, int, int>;
return add2(x, y);
}
}
}