C#通过Emit动态生成代码 首先需要声明一个程序集名称,
1//specifyanewassemblyname 2varassemblyName=newAssemblyName("Kitty"); 从当前应用程序域获取程序集构造器,
1//createassemblybuilder 2varassemblyBuilder=AppDomain.CurrentDomain 3.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave); 有几种动态程序集构造访问限制:
AssemblyBuilderAccess.Run;表示程序集可被执行,但不能被保存。 AssemblyBuilderAccess.Save;表示程序集可被保存,但不能被执行。 AssemblyBuilderAccess.RunAndSave;表示程序集可被保存并能被执行。 AssemblyBuilderAccess.ReflectionOnly;表示程序集只能用于反射上下文环境中,不能被执行。 AssemblyBuilderAccess.RunAndCollect;表示程序集可以被卸载并且内存会被回收。 在程序集中构造动态模块,
1//createmodulebuilder 2varmoduleBuilder=assemblyBuilder.DefineDynamicModule("KittyModule","Kitty.exe"); 模块即是代码的集合,一个程序集中可以有多个模块。并且理论上讲,每个模块可以使用不同的编程语言实现,例如C#/VB。 构造一个类型构造器,
1//createtypebuilderforaclass 2vartypeBuilder=moduleBuilder.DefineType("HelloKittyClass",TypeAttributes.Public); 通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。
复制代码 1//createmethodbuilder 2varmethodBuilder=typeBuilder.DefineMethod( 3"SayHelloMethod", 4MethodAttributes.Public|MethodAttributes.Static, 5null, 6null); 7 8//thengetthemethodilgenerator 9varil=methodBuilder.GetILGenerator(); 10 11//thencreatethemethodfunction 12il.Emit(OpCodes.Ldstr,"Hello,Kitty!"); 13il.Emit(OpCodes.Call, 14typeof(Console).GetMethod("WriteLine",newType[]{typeof(string)})); 15il.Emit(OpCodes.Call,typeof(Console).GetMethod("ReadLine")); 16il.Emit(OpCodes.Pop);//wejustreadsomethinghere,throwit. 17il.Emit(OpCodes.Ret); 复制代码 创建类型,
1//thencreatethewholeclasstype 2varhelloKittyClassType=typeBuilder.CreateType(); 如果当前程序集是可运行的,则设置一个程序入口,
1//setentrypointforthisassembly 2assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod")); 将动态生成的程序集保存成磁盘文件,
1//saveassembly 2assemblyBuilder.Save("Kitty.exe"); 此时,通过反编译工具,将Kitty.exe反编译成代码,
复制代码 1usingSystem; 2 3publicclassHelloKittyClass 4{ 5publicstaticvoidSayHelloMethod() 6{ 7Console.WriteLine("Hello,Kitty!"); 8Console.ReadLine(); 9} 10} 复制代码 运行结果,
完整代码 复制代码 1usingSystem; 2usingSystem.Reflection; 3usingSystem.Reflection.Emit; 4 5namespaceEmitIntroduction 6{ 7classProgram 8{ 9staticvoidMain(string[]args) 10{ 11//specifyanewassemblyname 12varassemblyName=newAssemblyName("Kitty"); 13 14//createassemblybuilder 15varassemblyBuilder=AppDomain.CurrentDomain 16.DefineDynamicAssembly(assemblyName, 17AssemblyBuilderAccess.RunAndSave); 18 19//createmodulebuilder 20varmoduleBuilder= 21assemblyBuilder.DefineDynamicModule( 22"KittyModule","Kitty.exe"); 23 24//createtypebuilderforaclass 25vartypeBuilder= 26moduleBuilder.DefineType( 27"HelloKittyClass",TypeAttributes.Public); 28 29//createmethodbuilder 30varmethodBuilder=typeBuilder.DefineMethod( 31"SayHelloMethod", 32MethodAttributes.Public|MethodAttributes.Static, 33null, 34null); 35 36//thengetthemethodilgenerator 37varil=methodBuilder.GetILGenerator(); 38 39//thencreatethemethodfunction 40il.Emit(OpCodes.Ldstr,"Hello,Kitty!"); 41il.Emitwww.wang027.com(OpCodes.Call, 42typeof(Console).GetMethod( 43"WriteLine",newType[]{typeof(string)})); 44il.Emit(OpCodes.Call, 45typeof(Console).GetMethod("ReadLine")); 46il.Emit(OpCodes.Pop);//wejustreadsomethinghere,throwit. 47il.Emit(OpCodes.Ret); 48 49//thencreatethewholeclasstype 50varhelloKittyClassType=typeBuilder.CreateType(); 51 52//setentrypointforthisassembly 53assemblyBuilder.SetEntryPoint( 54helloKittyClassType.GetMethod("SayHelloMethod")); 55 56//saveassembly 57assemblyBuilder.Save("Kitty.exe"); 58 59Console.WriteLine( 60"Hi,Dennis,aKittyassemblyhasbeengeneratedforyou."); 61Console.ReadLine(); 62} 63} 64} 复制代码 |
|