动态生成程序技术
DynamicProxy(无特殊说明的化,都指Castle's DynamicProxy for .net中的DynamicProxy技术)是建立在动态程序集生成技术的基础之上的,也就是说程序在运行时动态生成IL代码并被编译执行。
动态程序集生成技术 也就是说序在运行时动态生成IL代码并被编译执行
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.2052/cpguide/html/cpconemittingdynamicassemblies.htm
动态程序集System.Reflection.Emit 命名空间中的一组托管类型,它们允许编译器或工具在运行时发出元数据和 Microsoft 中间语言 (MSIL),或者也可以允许它们在磁盘上生成可移植可执行 (PE) 文件。脚本引擎和编译器是此命名空间的主要用户。在本节中,由 System.Reflection.Emit 命名空间提供的功能称为反射发出。
反射发出提供下列服务:
在运行时定义程序集,然后运行这些程序集并/或将它们保存到磁盘。
在运行时定义新程序集中的模块,然后运行这些模块并/或将它们保存到磁盘。
在运行时定义类型,创建这些类型的实例,并调用这些类型的方法。
为定义的模块定义可由调试器和代码分析器这样的工具使用的符号信息。
如果你想了解更多内容:见System.Reflection.Emit下面
改例子来自msdn,有兴趣大家运行下
下面是一个运行的代码示例: 见文件夹TypeResolve
usingSystem;usingSystem.Text;usingSystem.Threading;usingSystem.Reflection;usingSystem.Reflection.Emit;//手动写的类和程序与动态的程序集相同的功能//---//classPoint{////privateintx;//privateinty;////publicPoint(intix,intiy){////this.x=ix;//this.y=iy;////}////publicintDotProduct(Pointp){////return((this.x*p.x)+(this.y*p.y));////}////publicstaticvoidPointMain(){////Console.Write("Enterthe'x'valueforpoint1:");//intx1=Convert.ToInt32(Console.ReadLine());////Console.Write("Enterthe'y'valueforpoint1:");//inty1=Convert.ToInt32(Console.ReadLine());////Console.Write("Enterthe'x'valueforpoint2:");//intx2=Convert.ToInt32(Console.ReadLine());////Console.Write("Enterthe'y'valueforpoint2:");//inty2=Convert.ToInt32(Console.ReadLine());////Pointp1=newPoint(x1,y1);//Pointp2=newPoint(x2,y2);////Console.WriteLine("({0},{1}).({2},{3})={4}.",//x1,y1,x2,y2,p1.DotProduct(p2));////}////}//---classAssemblyBuilderDemo{publicstaticTypeBuildDynAssembly(){//声明类型TypepointType=null;//类型所在应用域AppDomaincurrentDom=Thread.GetDomain();//为你动态生成的程序集合输入名称Console.Write("Pleaseenteranameforyournewassembly:");StringBuilderasmFileNameBldr=newStringBuilder();asmFileNameBldr.Append(Console.ReadLine());asmFileNameBldr.Append(".exe");stringasmFileName=asmFileNameBldr.ToString();AssemblyNamemyAsmName=newAssemblyName();myAsmName.Name="MyDynamicAssembly";//定义程序集AssemblyBuildermyAsmBldr=currentDom.DefineDynamicAssembly(myAsmName,AssemblyBuilderAccess.RunAndSave);////withinittoreflectthetypePointinto.//定义模块ModuleBuildermyModuleBldr=myAsmBldr.DefineDynamicModule(asmFileName,asmFileName);//定义类名TypeBuildermyTypeBldr=myModuleBldr.DefineType("Point");//定义个类属性FieldBuilderxField=myTypeBldr.DefineField("x",typeof(int),FieldAttributes.Private);FieldBuilderyField=myTypeBldr.DefineField("y",typeof(int),FieldAttributes.Private);//定义构造函数TypeobjType=Type.GetType("System.Object");ConstructorInfoobjCtor=objType.GetConstructor(newType[0]);//定义参数Type[]ctorParams=newType[]{typeof(int),typeof(int)};ConstructorBuilderpointCtor=myTypeBldr.DefineConstructor(MethodAttributes.Public,CallingConventions.Standard,ctorParams);ILGeneratorctorIL=pointCtor.GetILGenerator();ctorIL.Emit(OpCodes.Ldarg_0);ctorIL.Emit(OpCodes.Call,objCtor);ctorIL.Emit(OpCodes.Ldarg_0);ctorIL.Emit(OpCodes.Ldarg_1);ctorIL.Emit(OpCodes.Stfld,xField);ctorIL.Emit(OpCodes.Ldarg_0);ctorIL.Emit(OpCodes.Ldarg_2);ctorIL.Emit(OpCodes.Stfld,yField);ctorIL.Emit(OpCodes.Ret);//定义DotProduct方法MethodBuilderpointDPBldr=myTypeBldr.DefineMethod("DotProduct",MethodAttributes.Public,typeof(int),newType[]{myTypeBldr});ILGeneratordpIL=pointDPBldr.GetILGenerator();dpIL.Emit(OpCodes.Ldarg_0);dpIL.Emit(OpCodes.Ldfld,xField);dpIL.Emit(OpCodes.Ldarg_1);dpIL.Emit(OpCodes.Ldfld,xField);dpIL.Emit(OpCodes.Mul_Ovf_Un);dpIL.Emit(OpCodes.Ldarg_0);dpIL.Emit(OpCodes.Ldfld,yField);dpIL.Emit(OpCodes.Ldarg_1);dpIL.Emit(OpCodes.Ldfld,yField);dpIL.Emit(OpCodes.Mul_Ovf_Un);dpIL.Emit(OpCodes.Add_Ovf_Un);dpIL.Emit(OpCodes.Ret);//定义PointMain()方法Console.WriteLine("DotProductbuilt.");MethodBuilderpointMainBldr=myTypeBldr.DefineMethod("PointMain",MethodAttributes.Public|MethodAttributes.Static,typeof(void),null);pointMainBldr.InitLocals=true;ILGeneratorpmIL=pointMainBldr.GetILGenerator();//我们调用四个方法//MethodInfotokens://-voidConsole.WriteLine(string)//-stringConsole.ReadLine()//-intConvert.Int32(string)//-voidConsole.WriteLine(string,object[])MethodInfowriteMI=typeof(Console).GetMethod("Write",newType[]{typeof(string)});MethodInforeadLineMI=typeof(Console).GetMethod("ReadLine",newType[0]);MethodInfoconvertInt32MI=typeof(Convert).GetMethod("ToInt32",newType[]{typeof(string)});Type[]wlParams=newType[]{typeof(string),typeof(object[])};MethodInfowriteLineMI=typeof(Console).GetMethod("WriteLine",wlParams);//Althoughwecouldjustrefertothelocalvariablesby//index(shortintsforLdloc/Stloc,bytesforLdLoc_S/Stloc_S),//thistime,we'lluseLocalBuildersforclarityandto//demonstratetheirusageandsyntax.//定义四个局部变量LocalBuilderx1LB=pmIL.DeclareLocal(typeof(int));LocalBuildery1LB=pmIL.DeclareLocal(typeof(int));LocalBuilderx2LB=pmIL.DeclareLocal(typeof(int));LocalBuildery2LB=pmIL.DeclareLocal(typeof(int));//定义两个动态类型的举办变量LocalBuilderpoint1LB=pmIL.DeclareLocal(myTypeBldr);LocalBuilderpoint2LB=pmIL.DeclareLocal(myTypeBldr);LocalBuildertempObjArrLB=pmIL.DeclareLocal(typeof(object[]));//完成//Console.Write("Enterthe'x'valueforpoint1:");//intx1=Convert.ToInt32(Console.ReadLine());pmIL.Emit(OpCodes.Ldstr,"Enterthe'x'valueforpoint1:");pmIL.EmitCall(OpCodes.Call,writeMI,null);pmIL.EmitCall(OpCodes.Call,readLineMI,null);pmIL.EmitCall(OpCodes.Call,convertInt32MI,null);pmIL.Emit(OpCodes.Stloc,x1LB);//完成//Console.Write("Enterthe'y'valueforpoint1:");//inty1=Convert.ToInt32(Console.ReadLine());pmIL.Emit(OpCodes.Ldstr,"Enterthe'y'valueforpoint1:");pmIL.EmitCall(OpCodes.Call,writeMI,null);pmIL.EmitCall(OpCodes.Call,readLineMI,null);pmIL.EmitCall(OpCodes.Call,convertInt32MI,null);pmIL.Emit(OpCodes.Stloc,y1LB);//Console.Write("Enterthe'x'valueforpoint2:");//intx2=Convert.ToInt32(Console.ReadLine());pmIL.Emit(OpCodes.Ldstr,"Enterthe'x'valueforpoint2:");pmIL.EmitCall(OpCodes.Call,writeMI,null);pmIL.EmitCall(OpCodes.Call,readLineMI,null);pmIL.EmitCall(OpCodes.Call,convertInt32MI,null);pmIL.Emit(OpCodes.Stloc,x2LB);//Console.Write("Enterthe'y'valueforpoint2:");//inty2=Convert.ToInt32(Console.ReadLine());pmIL.Emit(OpCodes.Ldstr,"Enterthe'y'valueforpoint2:");pmIL.EmitCall(OpCodes.Call,writeMI,null);pmIL.EmitCall(OpCodes.Call,readLineMI,null);pmIL.EmitCall(OpCodes.Call,convertInt32MI,null);pmIL.Emit(OpCodes.Stloc,y2LB);//Pointp1=newPoint(x1,y1);pmIL.Emit(OpCodes.Ldloc,x1LB);pmIL.Emit(OpCodes.Ldloc,y1LB);pmIL.Emit(OpCodes.Newobj,pointCtor);pmIL.Emit(OpCodes.Stloc,point1LB);//Pointp2=newPoint(x2,y2);pmIL.Emit(OpCodes.Ldloc,x2LB);pmIL.Emit(OpCodes.Ldloc,y2LB);pmIL.Emit(OpCodes.Newobj,pointCtor);pmIL.Emit(OpCodes.Stloc,point2LB);完成计算#region完成计算//Console.WriteLine("({0},{1}).({2},{3})={4}.",//x1,y1,x2,y2,p1.DotProduct(p2));//pmIL.Emit(OpCodes.Ldstr,"({0},{1}).({2},{3})={4}.");pmIL.Emit(OpCodes.Ldc_I4_5);pmIL.Emit(OpCodes.Newarr,typeof(Object));pmIL.Emit(OpCodes.Stloc,tempObjArrLB);pmIL.Emit(OpCodes.Ldloc,tempObjArrLB);pmIL.Emit(OpCodes.Ldc_I4_0);pmIL.Emit(OpCodes.Ldloc,x1LB);pmIL.Emit(OpCodes.Box,typeof(int));pmIL.Emit(OpCodes.Stelem_Ref);pmIL.Emit(OpCodes.Ldloc,tempObjArrLB);pmIL.Emit(OpCodes.Ldc_I4_1);pmIL.Emit(OpCodes.Ldloc,y1LB);pmIL.Emit(OpCodes.Box,typeof(int));pmIL.Emit(OpCodes.Stelem_Ref);pmIL.Emit(OpCodes.Ldloc,tempObjArrLB);pmIL.Emit(OpCodes.Ldc_I4_2);pmIL.Emit(OpCodes.Ldloc,x2LB);pmIL.Emit(OpCodes.Box,typeof(int));pmIL.Emit(OpCodes.Stelem_Ref);pmIL.Emit(OpCodes.Ldloc,tempObjArrLB);pmIL.Emit(OpCodes.Ldc_I4_3);pmIL.Emit(OpCodes.Ldloc,y2LB);pmIL.Emit(OpCodes.Box,typeof(int));pmIL.Emit(OpCodes.Stelem_Ref);pmIL.Emit(OpCodes.Ldloc,tempObjArrLB);pmIL.Emit(OpCodes.Ldc_I4_4);pmIL.Emit(OpCodes.Ldloc,point1LB);pmIL.Emit(OpCodes.Ldloc,point2LB);pmIL.EmitCall(OpCodes.Callvirt,pointDPBldr,null);pmIL.Emit(OpCodes.Box,typeof(int));pmIL.Emit(OpCodes.Stelem_Ref);pmIL.Emit(OpCodes.Ldloc,tempObjArrLB);pmIL.EmitCall(OpCodes.Call,writeLineMI,null);#endregion//结束pmIL.Emit(OpCodes.Ret);Console.WriteLine("PointMain(entrypoint)built.");pointType=myTypeBldr.CreateType();Console.WriteLine("Typebaked.");myAsmBldr.SetEntryPoint(pointMainBldr);myAsmBldr.Save(asmFileName);Console.WriteLine("Assemblysavedas'{0}'.",asmFileName);Console.WriteLine("Type'{0}'attheprompttorunyournew"+"dynamicallygenerateddotproductcalculator.",asmFileName);//Afterexecution,thisprogramwillhavegeneratedandwrittentodisk,//inthedirectoryyouexecuteditfrom,aprogramnamed//<name_you_entered_here>.exe.Youcanrunitbytyping//thenameyougaveitduringexecution,inthesamedirectorywhere//youexecutedthisprogram.returnpointType;}publicstaticvoidMain(){TypemyType=BuildDynAssembly();Console.WriteLine("---");//Let'sinvokethetype'Point'createdinourdynamicassembly.objectptInstance=Activator.CreateInstance(myType,newobject[]{0,0});myType.InvokeMember("PointMain",BindingFlags.InvokeMethod,null,ptInstance,newobject[0]);Console.ReadLine();}}