动态生成View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Reflection; 6 using System.Reflection.Emit; 7 using System.Threading; 8 9 namespace Reflx_Method 10 { 11 public class Class1 12 { 13 public Class1() 14 { } 15 /// <summary> 16 /// 17 /// </summary> 18 public void CreateDynamicType() 19 { 20 Type[] ctorParams = new Type[] {typeof(int), 21 typeof(int)}; 22 23 AppDomain myDomain = Thread.GetDomain(); 24 AssemblyName myAsmName = new AssemblyName(); 25 myAsmName.Name = "MyDynamicAssembly"; 26 27 AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly( 28 myAsmName, 29 AssemblyBuilderAccess.RunAndSave); 30 31 ModuleBuilder pointModule = myAsmBuilder.DefineDynamicModule("PointModule", 32 "Point.dll"); 33 34 TypeBuilder pointTypeBld = pointModule.DefineType("Point1", 35 TypeAttributes.Public); 36 37 FieldBuilder xField = pointTypeBld.DefineField("x", typeof(int), 38 FieldAttributes.Public); 39 FieldBuilder yField = pointTypeBld.DefineField("y", typeof(int), 40 FieldAttributes.Public); 41 42 43 Type objType = Type.GetType("System.Object"); 44 ConstructorInfo objCtor = objType.GetConstructor(new Type[0]); 45 46 ConstructorBuilder pointCtor = pointTypeBld.DefineConstructor( 47 MethodAttributes.Public, 48 CallingConventions.Standard, 49 ctorParams); 50 ILGenerator ctorIL = pointCtor.GetILGenerator(); 51 52 53 // First, you build the constructor. 首先,你建立的构造 54 ctorIL.Emit(OpCodes.Ldarg_0); 55 ctorIL.Emit(OpCodes.Call, objCtor); 56 ctorIL.Emit(OpCodes.Ldarg_0); 57 ctorIL.Emit(OpCodes.Ldarg_1); 58 ctorIL.Emit(OpCodes.Stfld, xField); 59 ctorIL.Emit(OpCodes.Ldarg_0); 60 ctorIL.Emit(OpCodes.Ldarg_2); 61 ctorIL.Emit(OpCodes.Stfld, yField); 62 ctorIL.Emit(OpCodes.Ret); 63 64 // Now, you'll build a method to output some information on the 65 // inside your dynamic class. This method will have the following 66 // definition in C#: 67 // public void WritePoint() 68 //现在,你将建立一个方法来输出一些信息 69 //内部动态类。这种方法将有以下 70 //在C#中定义: 71 //公共的无效WritePoint ( ) 72 73 MethodBuilder writeStrMthd = pointTypeBld.DefineMethod( 74 "WritePoint", 75 MethodAttributes.Public, 76 typeof(void), 77 null); 78 79 80 ILGenerator writeStrIL = writeStrMthd.GetILGenerator(); 81 82 // The below ILGenerator created demonstrates a few ways to create 83 // string output through STDIN. 84 // ILGenerator.EmitWriteLine(string) will generate a ldstr and a 85 // call to WriteLine for you. 86 //创建下面的ILGenerator演示了几种方法来创建 87 //字符串通过标准输入输出。 88 // ILGenerator.EmitWriteLine的(字符串)将生成一个ldstr与一个 89 //调用你的WriteLine 。 90 91 writeStrIL.EmitWriteLine("这个当前实例的值是:"); 92 93 // Here, you will do the hard work yourself. First, you need to create 94 // the string we will be passing and obtain the correct WriteLine overload 95 // for said string. In the below case, you are substituting in two values, 96 // so the chosen overload is Console.WriteLine(string, object, object). 97 //这里,你会做自己的辛勤工作。首先,你需要创建 98 //字符串,我们将通过并获得正确的WriteLine超载 99 //表示字符串。在下面的情况下,你是在两个值代 100 101 String inStr = "({0}, {1})"; 102 Type[] wlParams = new Type[] {typeof(string), 103 typeof(object), 104 typeof(object)}; 105 106 // We need the MethodInfo to pass into EmitCall later. 107 //我们的MethodInfo ,到EmitCall通过后的。 108 109 MethodInfo writeLineMI = typeof(Console).GetMethod( 110 "WriteLine", 111 wlParams); 112 113 // Push the string with the substitutions onto the stack. 114 // This is the first argument for WriteLine - the string one. 115 //推到堆栈上替换的字符串。 116 //这是第一个参数的WriteLine - 一个字符串。 117 118 writeStrIL.Emit(OpCodes.Ldstr, inStr); 119 120 // Since the second argument is an object, and it corresponds to 121 // to the substitution for the value of our integer field, you 122 // need to box that field to an object. First, push a reference 123 // to the current instance, and then push the value stored in 124 // field 'x'. We need the reference to the current instance (stored 125 // in local argument index 0) so Ldfld can load from the correct 126 // instance (this one). 127 //由于第二个参数是一个对象,它对应于 128 //我们的整数字段的值替代,你 129 //需要框字段对象。首先,推动一个参考 130 //当前实例,然后推值存储在 131 //字段'X' 。我们需要对当前实例的引用(存储 132 //本地参数索引0 ),因此Ldfld可以从正确的加载 133 //实例(一) 。 134 135 writeStrIL.Emit(OpCodes.Ldarg_0); 136 writeStrIL.Emit(OpCodes.Ldfld, xField); 137 138 // Now, we execute the box opcode, which pops the value of field 'x', 139 // returning a reference to the integer value boxed as an object. 140 //现在,我们执行操作码框,弹出领域的'X'的价值, 141 //返回一个整型值作为一个对象盒装的参考。 142 143 writeStrIL.Emit(OpCodes.Box, typeof(int)); 144 145 // Atop the stack, you'll find our string inStr, followed by a reference 146 // to the boxed value of 'x'. Now, you need to likewise box field 'y'. 147 //堆栈上面,你会发现我们的字符串INSTR ,其次是参考 148 // 'x'的装箱值。现在,你需要同样框场'Y' 。 149 150 writeStrIL.Emit(OpCodes.Ldarg_0); 151 writeStrIL.Emit(OpCodes.Ldfld, yField); 152 writeStrIL.Emit(OpCodes.Box, typeof(int)); 153 154 // Now, you have all of the arguments for your call to 155 // Console.WriteLine(string, object, object) atop the stack: 156 // the string InStr, a reference to the boxed value of 'x', and 157 // a reference to the boxed value of 'y'. 158 159 // Call Console.WriteLine(string, object, object) with EmitCall. 160 //现在,你有你的电话所有的参数 161 // Console.WriteLine (字符串,对象,对象)之上的堆栈: 162 //字符串INSTR , 'x'的装箱值的引用, 163 //装箱的值'Y'的参考。 164 165 //调用Console.WriteLine与EmitCall (字符串,对象,对象) 。 166 167 writeStrIL.EmitCall(OpCodes.Call, writeLineMI, null); 168 169 // Lastly, EmitWriteLine can also output the value of a field 170 // using the overload EmitWriteLine(FieldInfo). 171 //最后, EmitWriteLine也可以输出字段值 172 //使用的超载EmitWriteLine (的FieldInfo ) 。 173 174 writeStrIL.EmitWriteLine("The value of 'x' is:"); 175 writeStrIL.EmitWriteLine(xField); 176 writeStrIL.EmitWriteLine("The value of 'y' is:"); 177 writeStrIL.EmitWriteLine(yField); 178 179 // Since we return no value (void), the the ret opcode will not 180 // return the top stack value. 181 //由于我们没有返回值(无效) , ret操作码不会 182 //返回栈顶值。 183 184 writeStrIL.Emit(OpCodes.Ret); 185 186 187 Type type1 = pointTypeBld.CreateType(); 188 object[] ctorParams1 = new object[2]; 189 190 Console.Write("Enter a integer value for X: "); 191 string myX = Console.ReadLine(); 192 Console.Write("Enter a integer value for Y: "); 193 string myY = Console.ReadLine(); 194 195 Console.WriteLine("---"); 196 197 ctorParams1[0] = Convert.ToInt32(myX); 198 ctorParams1[1] = Convert.ToInt32(myY); 199 200 Type ptType = type1; 201 202 object ptInstance = Activator.CreateInstance(ptType, ctorParams1); 203 ptType.InvokeMember("WritePoint", 204 BindingFlags.InvokeMethod, 205 null, 206 ptInstance, 207 new object[0]); 208 209 myAsmBuilder.Save("Point.dll"); 210 //return type1; 211 212 } 213 } 214 }
调用View Code
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Reflection; 6 using System.Reflection.Emit; 7 8 namespace Reflx_Method 9 { 10 11 class Program 12 { 13 14 static void Main(string[] args) 15 { 16 new Class1().CreateDynamicType(); 17 } 18 19 } 20 21 } 22
等价于View Code
1 public class Point1 2 { 3 // Fields 4 public int x; 5 public int y; 6 7 // Methods 8 public Point1(int num1, int num2) 9 { 10 this.x = num1; 11 this.y = num2; 12 } 13 public void WritePoint() 14 { 15 Console.WriteLine("这个当前实例的值是:"); 16 Console.WriteLine("({0}, {1})", this.x, this.y); 17 Console.WriteLine("The value of 'x' is:"); 18 Console.Out.WriteLine(this.x); 19 Console.WriteLine("The value of 'y' is:"); 20 Console.Out.WriteLine(this.y); 21 } 22 } 23 24