• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

C# 实现 Aop [Emit动态生成代理类方式]

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
  1     using System.Reflection;
  2     using System.Reflection.Emit;
  3     public static class DefaultProxyBuilder
  4     {
  5         private static readonly Type VoidType = Type.GetType("System.Void"); //函数返回 void类型
  6 
  7         public static T CreateProxy<T>()
  8         {
  9             Type classType = typeof(T);
 10 
 11             string name = classType.Namespace + ".Aop"; //新的命名空间
 12             string fileName = name + ".dll";
 13 
 14 
 15             var assemblyName = new AssemblyName(name);         
 16             var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,AssemblyBuilderAccess.RunAndSave);
 17             var moduleBuilder = assemblyBuilder.DefineDynamicModule(name, fileName);//构建命名空间
 18             var aopType = BulidType(classType, moduleBuilder);
 19 
 20             assemblyBuilder.Save(fileName);
 21             return (T)Activator.CreateInstance(aopType);
 22         }
 23 
 24         private static Type BulidType(Type classType, ModuleBuilder moduleBuilder)
 25         {
 26             string className = classType.Name + "_Proxy";
 27 
 28             //定义类型
 29             var typeBuilder = moduleBuilder.DefineType(className,
 30                                                        TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class,
 31                                                        classType);//定义一个新类,继承classType
 32             //定义字段 _inspector 声明一个私有且只读的变量
 33             var inspectorFieldBuilder = typeBuilder.DefineField("_inspector", typeof(IInterceptor),
 34                                                                 FieldAttributes.Private | FieldAttributes.InitOnly);
 35             //构造函数 
 36             BuildCtor(classType, inspectorFieldBuilder, typeBuilder);
 37 
 38             //构造方法
 39             BuildMethod(classType, inspectorFieldBuilder, typeBuilder);
 40             Type aopType = typeBuilder.CreateType();
 41             return aopType;
 42         }
 43 
 44         private static void BuildMethod(Type classType, FieldBuilder inspectorFieldBuilder, TypeBuilder typeBuilder)
 45         {
 46             var methodInfos = classType.GetMethods();//获取 原类型
 47             foreach (var methodInfo in methodInfos)// 获取 虚函数 或 抽象函数
 48             {
 49                 if (!methodInfo.IsVirtual && !methodInfo.IsAbstract)
 50                     continue;
 51                 if (methodInfo.Name == "ToString")
 52                     continue;
 53                 if (methodInfo.Name == "GetHashCode")
 54                     continue;
 55                 if (methodInfo.Name == "Equals")
 56                     continue;
 57 
 58                 var parameterInfos = methodInfo.GetParameters();
 59                 var parameterTypes = parameterInfos.Select(p => p.ParameterType).ToArray();
 60                 var parameterLength = parameterTypes.Length;
 61                 var hasResult = methodInfo.ReturnType != VoidType;
 62 
 63                 var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name,
 64                                                              MethodAttributes.Public | MethodAttributes.Final |
 65                                                              MethodAttributes.Virtual
 66                                                              , methodInfo.ReturnType
 67                                                              , parameterTypes);
 68 
 69                 var il = methodBuilder.GetILGenerator();
 70 
 71                 //局部变量 声明
 72                 il.DeclareLocal(typeof(object)); //correlationState (emit 标签从0 开始:loc_0,loc_1,loc_2)
 73                 il.DeclareLocal(typeof(object)); //result
 74                 il.DeclareLocal(typeof(object[])); //parameters
 75 
 76                 #region BeforeCall
 77                 //BeforeCall(string operationName, object[] inputs);
 78                 il.Emit(OpCodes.Ldarg_0);
 79 
 80                 il.Emit(OpCodes.Ldfld, inspectorFieldBuilder);//获取字段_inspector
 81                 il.Emit(OpCodes.Ldstr, methodInfo.Name);//参数operationName
 82 
 83                 if (parameterLength == 0)//判断方法参数长度
 84                 {
 85                     il.Emit(OpCodes.Ldnull);//null -> 参数 inputs
 86                 }
 87                 else
 88                 {
 89                     //创建new object[parameterLength];
 90                     il.Emit(OpCodes.Ldc_I4, parameterLength);
 91                     il.Emit(OpCodes.Newarr, typeof(Object));
 92                     il.Emit(OpCodes.Stloc_2);//压入局部变量2 parameters
 93 
 94                     for (int i = 0, j = 1; i < parameterLength; i++, j++)
 95                     {
 96                         //object[i] = arg[j]
 97                         il.Emit(OpCodes.Ldloc_2);
 98                         il.Emit(OpCodes.Ldc_I4, 0);
 99                         il.Emit(OpCodes.Ldarg, j);
100                         if (parameterTypes[i].IsValueType)
101                             il.Emit(OpCodes.Box, parameterTypes[i]);//对值类型装箱
102                         il.Emit(OpCodes.Stelem_Ref);
103                     }
104                     il.Emit(OpCodes.Ldloc_2);//取出局部变量2 parameters-> 参数 inputs
105                 }
106 
107                 il.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod("BeforeCall"));//调用BeforeCall
108                 il.Emit(OpCodes.Stloc_0);//建返回压入局部变量0 correlationState
109                 #endregion
110 
111                 #region base.Call
112                 //Call methodInfo
113                 il.Emit(OpCodes.Ldarg_0); // arg_0: 
114                 //获取参数表
115                 for (int i = 1, length = parameterLength + 1; i < length; i++)
116                 {
117                     il.Emit(OpCodes.Ldarg_S, i);
118                 }
119                 il.Emit(OpCodes.Call, methodInfo);
120                 //将返回值压入 局部变量1result void就压入null
121                 if (!hasResult)
122                     il.Emit(OpCodes.Ldnull);
123                 else if (methodInfo.ReturnType.IsValueType)
124                     il.Emit(OpCodes.Box, methodInfo.ReturnType);//对值类型装箱
125                 il.Emit(OpCodes.Stloc_1); //返回值 保存到 result
126                 #endregion
127 
128                 #region AfterCall
129                 //AfterCall(string operationName, object returnValue, object correlationState);
130                 il.Emit(OpCodes.Ldarg_0);
131                 il.Emit(OpCodes.Ldfld, inspectorFieldBuilder);//获取字段_inspector
132                 il.Emit(OpCodes.Ldstr, methodInfo.Name);//参数 operationName
133                 il.Emit(OpCodes.Ldloc_1);//局部变量1 result
134                 il.Emit(OpCodes.Ldloc_0);// 局部变量0 correlationState
135                 il.Emit(OpCodes.Callvirt, typeof(IInterceptor).GetMethod("AfterCall"));
136                 #endregion
137 
138                 #region result
139                 //result 返回结果: void类型 直接返回函数,否则...
140                 if (!hasResult)
141                 {
142                     il.Emit(OpCodes.Ret);
143                     return;
144                 }
145                 il.Emit(OpCodes.Ldloc_1);//非void取出局部变量1 result
146                 if (methodInfo.ReturnType.IsValueType)
147                     il.Emit(OpCodes.Unbox_Any, methodInfo.ReturnType);//对值类型拆箱
148                 il.Emit(OpCodes.Ret);
149                 #endregion
150             }
151         }
152 
153         private static void BuildCtor(Type classType, FieldBuilder inspectorFieldBuilder, TypeBuilder typeBuilder)
154         {
155             {  //定义 代理类的 构造器
156                 var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis,
157                                                                 Type.EmptyTypes);
158                 var il = ctorBuilder.GetILGenerator();
159 
160                 il.Emit(OpCodes.Ldarg_0);
161                 il.Emit(OpCodes.Call, classType.GetConstructor(Type.EmptyTypes));//调用base的默认ctor
162                 il.Emit(OpCodes.Ldarg_0);
163                 //将typeof(classType)压入计算堆
164                 il.Emit(OpCodes.Ldtoken, classType);
165                 il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) }));
166                 //调用DefaultInterceptorFactory.Create(type)
167                 il.Emit(OpCodes.Call, typeof(DefaultInterceptorFactory).GetMethod("Create", new[] { typeof(Type) }));
168                 //将结果保存到字段_inspector
169                 il.Emit(OpCodes.Stfld, inspectorFieldBuilder);
170                 il.Emit(OpCodes.Ret);
171             }
172         }
173     }

注:http://www.189works.com/article-43203-1.html


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
C#中如何创建文件夹发布时间:2022-07-13
下一篇:
C# 代码重启windows服务发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap