首先需要聲明一個程式集名稱,
// specify a new assembly name var assemblyName = new AssemblyName("Kitty");
從當前應用程式定義域擷取程式集構造器,
// create assembly builder var assemblyBuilder = AppDomain.CurrentDomain .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
有幾種動態程式集構造訪問限制:
- AssemblyBuilderAccess.Run; 表示程式集可被執行,但不能被儲存。
- AssemblyBuilderAccess.Save; 表示程式集可被儲存,但不能被執行。
- AssemblyBuilderAccess.RunAndSave; 表示程式集可被儲存並能被執行。
- AssemblyBuilderAccess.ReflectionOnly; 表示程式集只能用於反射內容環境中,不能被執行。
- AssemblyBuilderAccess.RunAndCollect; 表示程式集可以被卸載並且記憶體會被回收。
在程式集中構造動態模組,
// create module builder var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");
模組即是代碼的集合,一個程式集中可以有多個模組。並且理論上講,每個模組可以使用不同的程式設計語言實現,例如C#/VB。
構造一個類型構造器,
// create type builder for a class var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);
通過類型構造器定義一個方法,擷取方法構造器,獲得方法構造器的IL產生器,通過編寫IL代碼來定義方法功能。
// create method builder var methodBuilder = typeBuilder.DefineMethod( "SayHelloMethod", MethodAttributes.Public | MethodAttributes.Static, null, null); // then get the method il generator var il = methodBuilder.GetILGenerator(); // then create the method function il.Emit(OpCodes.Ldstr, "Hello, Kitty!"); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine")); il.Emit(OpCodes.Pop); // we just read something here, throw it. il.Emit(OpCodes.Ret);
建立類型,
// then create the whole class type var helloKittyClassType = typeBuilder.CreateType();
如果當前程式集是可啟動並執行,則設定一個程式入口,
// set entry point for this assembly assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));
將動態產生的程式集儲存成磁碟檔案,
// save assembly assemblyBuilder.Save("Kitty.exe");
此時,通過反編譯工具,將Kitty.exe反編譯成代碼,
1 using System; 2 3 public class HelloKittyClass 4 { 5 public static void SayHelloMethod() 6 { 7 Console.WriteLine("Hello, Kitty!"); 8 Console.ReadLine(); 9 }10 }
運行結果,
完整代碼
1 using System; 2 using System.Reflection; 3 using System.Reflection.Emit; 4 5 namespace EmitIntroduction 6 { 7 class Program 8 { 9 static void Main(string[] args)10 {11 // specify a new assembly name12 var assemblyName = new AssemblyName("Kitty");13 14 // create assembly builder15 var assemblyBuilder = AppDomain.CurrentDomain16 .DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);17 18 // create module builder19 var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");20 21 // create type builder for a class22 var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);23 24 // create method builder25 var methodBuilder = typeBuilder.DefineMethod(26 "SayHelloMethod",27 MethodAttributes.Public | MethodAttributes.Static,28 null,29 null);30 31 // then get the method il generator32 var il = methodBuilder.GetILGenerator();33 34 // then create the method function35 il.Emit(OpCodes.Ldstr, "Hello, Kitty!");36 il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));37 il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));38 il.Emit(OpCodes.Pop); // we just read something here, throw it.39 il.Emit(OpCodes.Ret);40 41 // then create the whole class type42 var helloKittyClassType = typeBuilder.CreateType();43 44 // set entry point for this assembly45 assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));46 47 // save assembly48 assemblyBuilder.Save("Kitty.exe");49 50 Console.WriteLine("Hi, Dennis, a Kitty assembly has been generated for you.");51 Console.ReadLine();52 }53 }54 }
View Code
下載完整代碼
進一步閱讀使用Emit產生建構函式和屬性