C#中反射的使用(How to use reflect in CSharp)(3)Emit的使用

Emit意在动态构建一个可以执行(当然也就可以反射)或者只可以反射的动态库。

个人认为在不得不使用反射的情况下,使用Emit会使得效率提升空间很大。亦或者动态插件模式的软件设计中会用到。

依然2%的废话和98%的代码:

 1 using System;
 2 using System.Reflection;
 3 using System.Reflection.Emit;
 4 
 5 namespace ReflectionTest
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             //Emit
12             /*
13              Emit的知识隶属于反射的一部分,也是比较偏门的一部分。
14              在出现Dynamic和匿名类之后,它会有更小的用武之地,但仍然属于Reflection的知识范畴。
15              区别于“正常”的反射,Emit是动态的构建一个类,
16              比如,现在你没有Person.Dll,没有项目可以引用,没有可以反射的对象
17              那么你可能会想到Emit,它可以使你用代码构建出一个Person类,你甚至可以把动态构建的类保存成DLL,然后使用反射调用
18              虽然也是用C#去实现,但语法风格大不相同,强硬的理解,可以理解Emit暴漏给C#一些接口,让你去操作IL,然后生成动态库
19              在这次的blog中,我们的目的就是用代码构建出这个person类。OK,Let‘s start
20              */
21             //STEP 1. Give him a name
22             var assemblyName = new AssemblyName("PersonMoudle");
23 
24             //STEP 2. Build a assembly
25             var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
26                 AssemblyBuilderAccess.RunAndSave);
27 
28             //STEP 3. Add a moudle
29             var moudle = assemblyBuilder.DefineDynamicModule("PersonMoudle", "PersonMoudle.dll");
30 
31             //SETP 4. Add a Class
32             var typePart = moudle.DefineType("Person", TypeAttributes.Public);
33 
34             //SETP 5. Add a method for this Class
35             var methodPart = typePart.DefineMethod("SayHi", MethodAttributes.Public, null, null);
36 
37             //STEP 6. Imp the method
38             var il = methodPart.GetILGenerator();
39             il.EmitWriteLine("Hi! I‘m SayHi method!");
40             il.Emit(OpCodes.Ret);
41 
42             typePart.CreateType();
43             assemblyBuilder.Save("PersonMoudle.dll");
44 
45             //再比如,构建一个exe
46             var ad = AppDomain.CurrentDomain;
47             var am = new AssemblyName {Name = "TestEmit"};
48             var ab = ad.DefineDynamicAssembly(am, AssemblyBuilderAccess.Save);
49             var mb = ab.DefineDynamicModule("testmod", "输出一句话.exe");
50             var tb = mb.DefineType("TestEmit.Test", TypeAttributes.Public);
51             var metb = tb.DefineMethod("ConsoleWord", MethodAttributes.Public | MethodAttributes.Static, typeof (void),
52                 null);
53             ab.SetEntryPoint(metb);
54             ILGenerator il1 = metb.GetILGenerator();
55             il1.EmitWriteLine("Hello World");
56             il1.EmitWriteLine("按任意键退出……");
57             il1.Emit(OpCodes.Call, typeof (Console).GetMethod("ReadKey",new Type[]{}));//指定无参数的重载。生产环境的代码中应该有更加严格判断,具体指定个某个方法请翻前篇的文章。
58             il1.Emit(OpCodes.Ret);
59             tb.CreateType();
60             ab.Save("输出一句话.exe");
61             Console.ReadKey();
62         }
63     }
64 }

我们可以看到,执行完这个之后,在Debug里会生成我们想要的PersonMoudle.dll和输出一句话.exe、反编译后的dll和exe的执行效果:

C#中反射的使用(How to use reflect in CSharp)(3)Emit的使用

 

C#中反射的使用(How to use reflect in CSharp)(3)Emit的使用

上一篇:[置顶]Win2012R2的一个Bug安装群集后可能引发的软件崩溃问题及相应补丁


下一篇:C#(winform)实现不同DPI控件自适应1