小试Emit
67 views 十一月 25, 10 by Timothy.NET中的Emit,其实是个很强大的东东,它允许你在你的程序运行时,动态的生成代码。看到这里,也许大家会联想到Reflection,的确,Reflection也是我们平时用得比较多的一种技术,通过Reflection,我们能通过程序集中的元数据,动态的生成目标程序集的Instance,并执行它。而Emit的功能,恰恰和Reflection遥相呼应,前者允许我们动态的生成代码,后者允许我们动态的“查看”和运行代码。Emit和Reflection合在一起,简直就是双剑合璧,简直就是幸福的一家……难怪,微软也很邪恶的把Emit放在了System.Reflection.Emit。
其实哥平时的开发中,用得比较多的,还是Reflection(反射)了,不过早已久仰Emit的大名,又没闲暇时间来窥探一把,最近总算比较闲了,决心研究研究强大的Emit。
话不多说,代码是最有力的说明,先献上一个通过Emit动态创建并生成程序集的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using System; using System.Reflection; using System.Reflection.Emit; namespace Emit_Learn { class Program { static void Main(string[] args) { var name = new AssemblyName("HelloEmit"); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave); //创建程序集 var modelBuilder = assemblyBuilder.DefineDynamicModule("HelloEmit", "HelloEmit.dll"); //创建模块 var typeBuilder = modelBuilder.DefineType("HelloEmit"); //定义类型 var methodBuilder = typeBuilder.DefineMethod("Execute", MethodAttributes.Public, null, null); //创建MethodBuilder var il = methodBuilder.GetILGenerator(); //获取ILGenerator,用于生成方法的IL il.Emit(OpCodes.Ldstr, "Hello, Emit"); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); il.Emit(OpCodes.Ret); typeBuilder.CreateType(); assemblyBuilder.Save("HelloEmit.dll"); //保存动态生成的程序集到磁盘文件 } } } |
在IDE中输入以上代码,F5运行,你会发现,在你的程序的Debug目录,会生成一个HelloEmit.dll。没错,这就是我们的程序动态生成的程序集,并且它是可执行的。以上的代码,动态生成的程序集,包含一个叫HelloEmit的类,类中有一个public属性的Execute方法。方法中调用Console输出字符串:Hello,Emit
这个类,等价于如下的C#代码:
1 2 3 4 5 6 7 8 | internal class HelloEmit { // Methods public void Execute() { Console.WriteLine("Hello, Emit"); } } |
我们也可以使用.NET Reflector一类的工具,打开生成的Dll查看,顺便验证一下。
Emit适用的场景:适用于对业务灵活性要求很高的系统,可以在运行时动态更改业务逻辑,并动态生成代码。






