c# 使用反射Reflection的Emit实现动态创建元数据及可执行文件
1 void Main() 2 { 3 string projectName = "HelloWorld"; 4 5 AssemblyName assemblyName = new AssemblyName() 6 { 7 Name = projectName 8 }; 9 10 //生成一个动态程序集 11 AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save); 12 13 //生成程序集模块 14 ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(projectName, projectName + ".exe",true); 15 16 //设置类 17 TypeBuilder typeBuilder = moduleBuilder.DefineType("Program", TypeAttributes.Class); 18 //设置方法 19 MethodBuilder mainMethodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(void),Type.EmptyTypes); 20 21 //指定IL 22 ILGenerator ilMain = mainMethodBuilder.GetILGenerator(); 23 //声明string类型变量 24 LocalBuilder msgLocal = ilMain.DeclareLocal(typeof(string)); 25 //定义变量名 26 msgLocal.SetLocalSymInfo("letter"); 27 ilMain.Emit(OpCodes.Ldstr,"hello world"); 28 ilMain.Emit(OpCodes.Stloc,msgLocal); 29 ilMain.Emit(OpCodes.Ldloc, msgLocal); 30 ilMain.EmitCall(OpCodes.Call, Type.GetType("System.Console").GetMethod("WriteLine", new Type[] {typeof(string)}),null); 31 ilMain.Emit(OpCodes.Ret); 32 33 typeBuilder.CreateType(); 34 35 assemblyBuilder.SetEntryPoint(mainMethodBuilder); 36 assemblyBuilder.Save(projectName + ".exe"); 37 38 39 } 40 41 // Define other methods and classes here
另一示例:
1 // define assembly and module 2 var propertyName = "Name"; 3 var propertyType = typeof(string); 4 var ab = AssemblyBuilder.DefineDynamicAssembly( 5 new AssemblyName("dynamicAssembly"), 6 AssemblyBuilderAccess.Save); 7 var mb = ab.DefineDynamicModule("dynamicModule", "dynamicModule.dll"); 8 9 // define type, field and property 10 var tb = mb.DefineType("dynamicType"); 11 var fb = tb.DefineField("_name", propertyType, FieldAttributes.Private); 12 var pb = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, Type.EmptyTypes); 13 var get = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes); 14 var set = tb.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType }); 15 16 // write the IL for the get method 17 var getIl = get.GetILGenerator(); 18 getIl.Emit(OpCodes.Ldarg_0); // this 19 getIl.Emit(OpCodes.Ldfld, fb); // _name field 20 getIl.Emit(OpCodes.Ret); 21 22 // write the IL for the set method 23 var setIl = set.GetILGenerator(); 24 Label exitSet = setIl.DefineLabel(); // define label to jump in case condition is false 25 setIl.Emit(OpCodes.Ldarg_0); // this 26 setIl.Emit(OpCodes.Ldfld, fb); // _name field 27 setIl.Emit(OpCodes.Ldarg_1); // value 28 var inequality = propertyType.GetMethod("op_Inequality", new[] { propertyType, propertyType }); 29 setIl.Emit(OpCodes.Call, inequality); // '!=' method 30 setIl.Emit(OpCodes.Brfalse_S, exitSet); // check for inequality 31 setIl.Emit(OpCodes.Ldstr, "changedto:"); // load string literal 32 setIl.Emit(OpCodes.Ldarg_1); // value 33 var concat = propertyType.GetMethod("Concat", new[] { propertyType, propertyType }); 34 setIl.Emit(OpCodes.Call, concat); // concat two strings (literal + value) 35 var writeline = typeof(Console).GetMethod("WriteLine", new[] { propertyType }); 36 setIl.Emit(OpCodes.Call, writeline); // write 37 setIl.Emit(OpCodes.Ldarg_0); // this 38 setIl.Emit(OpCodes.Ldarg_1); // value 39 setIl.Emit(OpCodes.Stfld, fb); // save the new value into _name 40 setIl.MarkLabel(exitSet); // mark the label 41 setIl.Emit(OpCodes.Ret); // return 42 pb.SetGetMethod(get); 43 pb.SetSetMethod(set); 44 45 tb.CreateType(); // complete the type 46 ab.Save("dynamicModule.dll"); // save the assembly to disk
结果代码
1 internal class dynamicType 2 { 3 private string _name; 4 5 public string Name 6 { 7 get 8 { 9 return this._name; 10 } 11 set 12 { 13 if (this._name != value) 14 { 15 Console.WriteLine("changedto:" + value); 16 this._name = value; 17 } 18 } 19 } 20 }