『.Net反射』ILGenerator.Emit 动态MSIL 编程

时间:2022-07-22
本文章向大家介绍『.Net反射』ILGenerator.Emit 动态MSIL 编程,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

什么都不说,直接贴代码:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             SetValue();
 6         }
 7 
 8         public static void SetValue()
 9         {
10             int temp1 = 123;
11             int temp2 = 234;
12             int sum = temp1 + temp2;
13             string sumStr = sum.ToString();
14 
15             Console.WriteLine(sumStr);
16         }
17     }

对应的 ILGenerator.Emit 代码:

  1  class Program
  2     {
  3         static void Main(string[] args)
  4         {
  5 //.method public hidebysig static void  SetValue() cil managed
  6 //{
  7 //  // 代码大小       30 (0x1e)
  8 //  .maxstack  2
  9 //  .locals init ([0] int32 temp1,
 10 //           [1] int32 temp2,
 11 //           [2] int32 sum,
 12 //           [3] string sumStr)
 13 //  IL_0000:  nop
 14 //  IL_0001:  ldc.i4.s   123
 15 //  IL_0003:  stloc.0
 16 //  IL_0004:  ldc.i4     0xea
 17 //  IL_0009:  stloc.1
 18 //  IL_000a:  ldloc.0
 19 //  IL_000b:  ldloc.1
 20 //  IL_000c:  add
 21 //  IL_000d:  stloc.2
 22 //  IL_000e:  ldloca.s   sum
 23 //  IL_0010:  call       instance string [mscorlib]System.Int32::ToString()
 24 //  IL_0015:  stloc.3
 25 //  IL_0016:  ldloc.3
 26 //  IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
 27 //  IL_001c:  nop
 28 //  IL_001d:  ret
 29 //} // end of method Program::SetValue
 30             SetValue();
 31         }
 32 
 33         public static void SetValue()
 34         {
 35             DynamicMethod dm = new DynamicMethod("SetValueMethod", null, new Type[] { /*typeof(object), typeof(object)*/ }, true);
 36 
 37             ILGenerator generator = dm.GetILGenerator();
 38 
 39             generator.DeclareLocal(typeof(int));    //声明变量
 40             generator.DeclareLocal(typeof(int));    //声明变量
 41             generator.DeclareLocal(typeof(int));    //声明变量
 42             generator.DeclareLocal(typeof(string));    //声明变量
 43 
 44             //加载参数1,需要注意的是静态方法Ldarg_0对应的是参数1,
 45             //实例方法Ldarg_0对应的是this指针,Ldarg_1对应的是参数1,
 46             //即每个实例方法都传递一个隐含的this指针
 47 
 48             //int temp1 = 123;
 49             //int temp2 = 234;
 50             //int sum = temp1 + temp2;
 51             //string sumStr = sum.ToString();
 52             //Console.WriteLine(sumStr);
 53 
 54             //temp1 = 123
 55             generator.Emit(OpCodes.Ldc_I4, 123);
 56             generator.Emit(OpCodes.Stloc_0);
 57 
 58             //temp2 = 234
 59             generator.Emit(OpCodes.Ldc_I4, 234);
 60             generator.Emit(OpCodes.Stloc_1);
 61 
 62             //sum = temp1 + temp2
 63             generator.Emit(OpCodes.Ldloc_0);
 64             generator.Emit(OpCodes.Ldloc_1);
 65             generator.Emit(OpCodes.Add);
 66             generator.Emit(OpCodes.Stloc_2);
 67 
 68             //string sumStr = sum.ToString();
 69             //ldloca.s   sum
 70             //call       instance string [mscorlib]System.Int32::ToString()
 71             //stloc.3
 72             //调用成员函数
 73             generator.Emit(OpCodes.Ldloca_S, 2); //generator.Emit(OpCodes.Ldloc_2);
 74             MethodInfo toStringMethodInfo = typeof(Int32).GetMethod("ToString", new Type[] { });
 75             generator.Emit(OpCodes.Call, toStringMethodInfo);
 76             //generator.EmitCall(OpCodes.Call, toStringMethodInfo, null);   //和上面代码 同意思
 77             generator.Emit(OpCodes.Stloc_3);
 78 
 79             //Console.WriteLine(sumStr);
 80             //IL_0016:  ldloc.3
 81             //IL_0017:  call       void [mscorlib]System.Console::WriteLine(string)
 82             //调用静态函数
 83             generator.Emit(OpCodes.Ldloc_3);
 84             MethodInfo writeLineMethodInfo = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
 85             generator.Emit(OpCodes.Call, writeLineMethodInfo);
 86             //generator.EmitCall(OpCodes.Call, writeLineMethodInfo, null);   //和上面代码 同意思
 87 
 88             //generator.Emit(OpCodes.Pop);   //是否是 无返回值函数 调用之后,不用弹出堆栈?
 89 
 90             //return
 91             generator.Emit(OpCodes.Ret);   //函数执行完成
 92 
 93             
 94 
 95 
 96             //将函数作为 委托
 97             VoidNoParamsMethod delegateMethod = (VoidNoParamsMethod)dm.CreateDelegate(typeof(VoidNoParamsMethod));
 98             //执行委托
 99             delegateMethod.Invoke();
100         }
101 
102 
103         public delegate void VoidNoParamsMethod();
104     }

--------------------------------------------------------------------------

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             TestClass testClass = new TestClass();
 6             testClass.Age = 1234;
 7             int age = testClass.Age;
 8             Console.WriteLine(age);
 9         }
10 
11 
12          
13     }
14 
15     public class TestClass
16     {
17         public int Age;
18     }

对应的 ILGenerator.Emit 代码:

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5 //.method private hidebysig static void  Main(string[] args) cil managed
 6 //{
 7 //  .entrypoint
 8 //  // 代码大小       33 (0x21)
 9 //  .maxstack  2
10 //  .locals init ([0] class ComplexSetValue.TestClass testClass,
11 //           [1] int32 age)
12 //  IL_0000:  nop
13 //  IL_0001:  newobj     instance void ComplexSetValue.TestClass::.ctor()
14 //  IL_0006:  stloc.0
15 //  IL_0007:  ldloc.0
16 //  IL_0008:  ldc.i4     0x4d2
17 //  IL_000d:  stfld      int32 ComplexSetValue.TestClass::Age
18 //  IL_0012:  ldloc.0
19 //  IL_0013:  ldfld      int32 ComplexSetValue.TestClass::Age
20 //  IL_0018:  stloc.1
21 //  IL_0019:  ldloc.1
22 //  IL_001a:  call       void [mscorlib]System.Console::WriteLine(int32)
23 //  IL_001f:  nop
24 //  IL_0020:  ret
25 //} // end of method Program::Main
26 
27             DynamicMethod dm = new DynamicMethod("SetValueMethod", null, new Type[] { /*typeof(object), typeof(object)*/ }, true);
28 
29             ILGenerator generator = dm.GetILGenerator();
30 
31             generator.DeclareLocal(typeof(TestClass));  //声明变量
32             generator.DeclareLocal(typeof(int));  //声明变量
33 
34             //加载参数1,需要注意的是静态方法Ldarg_0对应的是参数1,
35             //实例方法Ldarg_0对应的是this指针,Ldarg_1对应的是参数1,
36             //即每个实例方法都传递一个隐含的this指针
37 
38             //TestClass testClass = new TestClass();
39             //testClass.Age = 1234;
40             //int age = testClass.Age;
41             //Console.WriteLine(age);
42 
43             //TestClass testClass = new TestClass();
44             //newobj     instance void ComplexSetValue.TestClass::.ctor()
45             ConstructorInfo testClassConstructor = typeof (TestClass).GetConstructor(new Type[] {});
46             generator.Emit(OpCodes.Newobj, testClassConstructor);
47             generator.Emit(OpCodes.Stloc_0);
48 
49             //testClass.Age = 1234;
50             //ldloc.0
51             //ldc.i4     0x4d2  //1234
52             //stfld      int32 ComplexSetValue.TestClass::Age
53             generator.Emit(OpCodes.Ldloc_0);
54             generator.Emit(OpCodes.Ldc_I4, 1234);
55             FieldInfo fieldInfo = typeof (TestClass).GetField("Age");
56             generator.Emit(OpCodes.Stfld, fieldInfo);
57 
58             //int age = testClass.Age;
59             //ldloc.0
60             //ldfld      int32 ComplexSetValue.TestClass::Age
61             //stloc.1
62             generator.Emit(OpCodes.Ldloc_0);
63             generator.Emit(OpCodes.Ldfld, fieldInfo);
64             generator.Emit(OpCodes.Stloc_1);
65 
66             //Console.WriteLine(age);
67             //ldloc.0
68             //call       void [mscorlib]System.Console::WriteLine(object)
69             generator.Emit(OpCodes.Ldloc_1);
70             MethodInfo writeLineMethodInfo = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });
71             generator.Emit(OpCodes.Call, writeLineMethodInfo);
72             //generator.EmitCall(OpCodes.Call, writeLineMethodInfo, null);   //和上面代码 同意思
73 
74             //generator.Emit(OpCodes.Pop);   //是否是 无返回值函数 调用之后,不用弹出堆栈?
75 
76             //return
77             generator.Emit(OpCodes.Ret);   //函数执行完成
78 
79 
80             //将函数作为 委托
81             VoidNoParamsMethod delegateMethod = (VoidNoParamsMethod)dm.CreateDelegate(typeof(VoidNoParamsMethod));
82             //执行委托
83             delegateMethod.Invoke();
84         }
85     }
86 
87     public delegate void VoidNoParamsMethod();
88 
89     public class TestClass
90     {
91         public int Age;
92     }