基礎才是重中之重~Emit動態(tai)構建(jian)方(fang)法(參數(shu)和返回(hui)值)
對于Emit我們知道它的可以動態構建程序集,類型,方法,屬性等,或者說只要手動使用C#創建的東西使用Emit也都可以動態創建它們,Emit由于它的特別之處,所以在很多領域得到了廣泛的應用,像最近比較火的AOP技術,它最核心的功能就是方法攔截了,我們使用Emit也是可以實現方法攔截功能的,詳細可以看大叔這篇文章《Lind.DDD.Aspects通過Plugins實現方法的動態攔截~Lind里的AOP》。
有參數,沒有返回值的方法構建與調用
[TestMethod] public void BulidMethod() { //得到當前的(de)應用程(cheng)序(xu)域 AppDomain appDm = AppDomain.CurrentDomain; //初(chu)始化AssemblyName的一個實例 AssemblyName an = new AssemblyName(); //設(she)置程序集的(de)名稱 an.Name = "EmitLind"; //動態(tai)的(de)在當(dang)前(qian)應用程序域(yu)創建一(yi)個應用程序集 AssemblyBuilder ab = appDm.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); //動態在程序集內(nei)創建一個模塊 ModuleBuilder mb = ab.DefineDynamicModule("EmitLind"); //動態的在模塊內(nei)創建一個類(lei) TypeBuilder tb = mb.DefineType("HelloEmit", TypeAttributes.Public | TypeAttributes.Class); //動(dong)態的為類里創建(jian)一(yi)個方(fang)法 MethodBuilder mdb = tb.DefineMethod("HelloWord", MethodAttributes.Public, null, new Type[] { typeof(string) }); //得(de)到(dao)該(gai)方法的ILGenerator ILGenerator ilG = mdb.GetILGenerator(); ilG.Emit(OpCodes.Ldstr, "Hello:{0}"); //加載傳入方法的參數到堆棧 ilG.Emit(OpCodes.Ldarg_1); //調用Console.WriteLine方法,輸出傳入的字符 ilG.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(string) })); ilG.Emit(OpCodes.Ret); //創建類的Type對象(xiang) Type tp = tb.CreateType(); //實(shi)例化一個類 object ob = Activator.CreateInstance(tp); //得到類中的方(fang)法,通過Invoke來觸發方(fang)法的調(diao)用.. MethodInfo mdi = tp.GetMethod("HelloWord"); mdi.Invoke(ob, new object[] { "Hello Lind" }); }
有參數,同時有返回值的方法構建與調用
public void BulidMethodRet() { //得(de)到當前的(de)應用程序域 AppDomain appDm = AppDomain.CurrentDomain; //初始化AssemblyName的一個實例 AssemblyName an = new AssemblyName(); //設置(zhi)程(cheng)序集的名稱 an.Name = "EmitLind"; //動態的在當前應用程序域創建一個(ge)應用程序集 AssemblyBuilder ab = appDm.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); //動(dong)態在程序集(ji)內(nei)創建一(yi)個模塊 ModuleBuilder mb = ab.DefineDynamicModule("EmitLind"); //動(dong)態的在模塊內創(chuang)建一(yi)個類 TypeBuilder tb = mb.DefineType("HelloEmit", TypeAttributes.Public | TypeAttributes.Class); //動態(tai)的為類里創建一(yi)個方(fang)法(fa) MethodBuilder mdb = tb.DefineMethod( "HelloWorldReturn", MethodAttributes.Public, typeof(string), new Type[] { typeof(string), typeof(string) }); //得到該方法的ILGenerator ILGenerator ilG = mdb.GetILGenerator(); ilG.Emit(OpCodes.Ldstr, "你好:{0}-{1}"); //加載傳入方法的(de)參數(shu)到堆棧 ilG.Emit(OpCodes.Ldarg_1); ilG.Emit(OpCodes.Ldarg_2); //調(diao)用Console.WriteLine方法(fa),輸(shu)出傳(chuan)入的(de)字符 ilG.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string), typeof(string) ,typeof(string)})); // ilG.Emit(OpCodes.Pop);//加這個就有問(wen)題了 //返(fan)回(hui)值部分 LocalBuilder local = ilG.DeclareLocal(typeof(string)); ilG.Emit(OpCodes.Ldstr, "Return Value:{0}"); ilG.Emit(OpCodes.Ldarg_1); ilG.Emit(OpCodes.Call, typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(string) })); ilG.Emit(OpCodes.Stloc_0, local); ilG.Emit(OpCodes.Ldloc_0, local); ilG.Emit(OpCodes.Ret); //創建類的(de)Type對象 Type tp = tb.CreateType(); //實例(li)化一個類 object ob = Activator.CreateInstance(tp); //得到類中的方法,通過Invoke來觸(chu)發(fa)方法的調用.. MethodInfo mdi = tp.GetMethod("HelloWorldReturn"); mdi.Invoke(ob, new object[] { "Hello Lind","OK" }); }