.net提供了在运行期动态创建类型的机制。Spring.net 中应用其中的实现来实现AOPProxy.
对于类,需要制定Assembly, Module, Class Name以及类中的成员。
对MSDN上面的代码解释一下:
首先制定需要创建类型的Assembly和Module
创建AssemblyBuilder和ModuleBuilder AssemblyBuilder myAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName("Banks.APP"), AssemblyBuilderAccess.RunAndSave); ModuleBuilder pointModule = myAsmBuilder.DefineDynamicModule("Banks.APP", "1234.dll");
通过使用ModuleBuilder创建TypeBuilder
创建TypeBuilderTypeBuilder matrixTypeBld = pointModule.DefineType("Matrix", TypeAttributes.Public);
创建成员字段
创建TypeBuilder FieldBuilder xField = matrixTypeBld.DefineField("x", typeof(int), FieldAttributes.Public); FieldBuilder yField = matrixTypeBld.DefineField("y", typeof(int), FieldAttributes.Public); FieldBuilder zField = matrixTypeBld.DefineField("z", typeof(int), FieldAttributes.Public);
创建ConstructorBuilder
创建ConstructorBuilderConstructorBuilder pointCtor = matrixTypeBld.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
ctorParams);
ILGenerator ctorIL = pointCtor.GetILGenerator();
将以下代码以IL代码的形式写入
构造函数代码this.x = x; this.y = y; this.z = z;
实际IL代码类似如下:
构造函数IL代码 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: nop IL_0008: ldarg.0 IL_0009: ldarg.1 IL_000a: stfld int32 Matrix::x IL_000f: ldarg.0 IL_0010: ldarg.2 IL_0011: stfld int32 Matrix::y IL_0016: ldarg.0 IL_0017: ldarg.3 IL_0018: stfld int32 Matrix::z IL_001d: nop IL_001e: ret
实际代码:
生成运行期构造函数 ctorIL.Emit(OpCodes.Ldarg_0); Type objType = typeof(Object); ConstructorInfo objCtor = objType.GetConstructor(new Type[0]); // Here, we wish to create an instance of System.Object by invoking its // constructor, as specified above. ctorIL.Emit(OpCodes.Call, objCtor); // Now, we'll load the current instance ref in arg 0, along // with the value of parameter "x" stored in arg 1, into stfld. ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_1); ctorIL.Emit(OpCodes.Stfld, xField); // Now, we store arg 2 "y" in the current instance with stfld. ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_2); ctorIL.Emit(OpCodes.Stfld, yField); // Last of all, arg 3 "z" gets stored in the current instance. ctorIL.Emit(OpCodes.Ldarg_0); ctorIL.Emit(OpCodes.Ldarg_3); ctorIL.Emit(OpCodes.Stfld, zField); // Our work complete, we return. ctorIL.Emit(OpCodes.Ret);
通过对比真实的IL代码,ldarg_0实际上就是获得this的引用,MSDN中没有详细解释arg_0,只是说明:Load argument 0 onto stack
arg_1, arg_2, arg_3是实际构造函数的三个参数,将其各自赋值到三个类成员变量x,y,z中。