国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

大家一起Aop

2019-11-17 03:20:20
字體:
來源:轉載
供稿:網友

大家一起Aop

一、前言

  1.在項目中無處不充斥著記錄日志的代碼,各種try catch,實在是有點看著不爽。這不,果斷要想法子偷個懶兒。

二、摘要

鄙人不才,先總結一下個人想到的可實現AOP的幾種思路:

  1.通過繼承特定實例,重寫虛方法(C#中如virtual、override方法),動態構建一個該實例的子類,進行調用。

  2.通過實現特定實例上的接口,動態構建一個該接口的實現類,切入AOP代碼,內部包裹特定實例的方法。

  3.最簡單的一種方式,通過給特定實例繼承MarshalByRefObject類,并且用繼承RealPRoxy的代理類進行構造包裹。

代碼比較少,有些Emit基礎的童鞋應該很容易看懂,接下去直接上核心代碼。

三、繼承類模式

  1 if (!method.IsPublic || !method.IsVirtual/*非虛方法無法重寫*/|| method.IsFinal /*Final方法無法重寫,如interface的實現方法標記為 virtual final*/ || IsObjectMethod(method)) return;  2   3             const MethodAttributes methodattributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;  4             Type[] paramTypes = method.GetParameters().Select(ent => ent.ParameterType).ToArray();  5             MethodBuilder mb = _typeBuilder.DefineMethod(method.Name, methodattributes, method.ReturnType, paramTypes);  6             ILGenerator il = mb.GetILGenerator();  7   8             #region 初始化本地變量和返回值  9             //加載所有參數到本地object[],實例方法第一個參數是this,已排除 10             LoadArgsIntoLocalField(il, paramTypes); 11  12             //如果有返回值,定義返回值變量 13             bool isReturnVoid = method.ReturnType == typeof(void); 14             LocalBuilder result = null; 15             if (!isReturnVoid) 16                 result = il.DeclareLocal(method.ReturnType); 17  18             //定義MethodInfo變量,下面會用到(傳遞到Aop的上下文中) 19             var methodInfo = il.DeclareLocal(typeof(MethodBase)); 20             il.Emit(OpCodes.Call, typeof(MethodBase).GetMethod("GetCurrentMethod", Type.EmptyTypes)); 21             il.Emit(OpCodes.Stloc, methodInfo); 22             #endregion 23  24             #region 初始化aspectContext 25             Type contextType = typeof(AspectContext); 26             var context = il.DeclareLocal(contextType); 27             ConstructorInfo info = contextType.GetConstructor(Type.EmptyTypes); 28             il.Emit(OpCodes.Newobj, info); 29             il.Emit(OpCodes.Stloc, context); 30             #endregion 31  32             #region 給AspectContext的參數值屬性ParameterArgs,MethodInfo賦值 33             il.Emit(OpCodes.Ldloc, context); 34             il.Emit(OpCodes.Ldloc_0); 35             il.Emit(OpCodes.Call, contextType.GetMethod("set_ParameterArgs")); 36  37             il.Emit(OpCodes.Ldloc, context); 38             il.Emit(OpCodes.Ldloc, methodInfo); 39             il.Emit(OpCodes.Call, contextType.GetMethod("set_MethodInfo")); 40             #endregion 41  42             AspectAttribute[] attrs = GetAspectAttributes(method); 43             int attrLen = attrs.Length; 44             LocalBuilder[] lbs = new LocalBuilder[attrLen]; 45             MethodInfo[] endInvokeMethods = new MethodInfo[attrLen]; 46             MethodInfo[] invokingExceptionMethods = new MethodInfo[attrLen]; 47  48             #region 初始化標記的切面對象,并調用切面對象的BeforeInvoke方法 49             for (int i = 0; i < attrLen; i++) 50             { 51                 var tmpAttrType = attrs[i].GetType(); 52                 var tmpAttr = il.DeclareLocal(tmpAttrType); 53                 ConstructorInfo tmpAttrCtor = tmpAttrType.GetConstructor(Type.EmptyTypes); 54  55                 il.Emit(OpCodes.Newobj, tmpAttrCtor); 56                 il.Emit(OpCodes.Stloc, tmpAttr); 57  58                 var beforeInvokeMethod = tmpAttrType.GetMethod("BeforeInvoke"); 59                 endInvokeMethods[i] = tmpAttrType.GetMethod("AfterInvoke"); 60                 invokingExceptionMethods[i] = tmpAttrType.GetMethod("InvokingException"); 61  62                 il.Emit(OpCodes.Ldloc, tmpAttr); 63                 il.Emit(OpCodes.Ldloc, context); 64                 il.Emit(OpCodes.Callvirt, beforeInvokeMethod); 65                 il.Emit(OpCodes.Nop); 66  67                 lbs[i] = tmpAttr; 68             } 69             #endregion 70  71             //try 72             il.BeginExceptionBlock(); 73  74             #region 調用實現方法 75             if (!method.IsAbstract) 76             { 77                 //類對象,參數值依次入棧 78                 for (int i = 0; i <= paramTypes.Length; i++) 79                     il.Emit(OpCodes.Ldarg, i); 80  81                 //調用基類的方法 82                 il.Emit(OpCodes.Call, method); 83  84                 if (!isReturnVoid) 85                 { 86                     il.Emit(OpCodes.Stloc, result); 87  88                     // 89                     il.Emit(OpCodes.Ldloc, context); 90                     il.Emit(OpCodes.Ldloc, result); 91                     if (method.ReturnType.IsValueType) 92                         il.Emit(OpCodes.Box, method.ReturnType); 93                     il.Emit(OpCodes.Call, contextType.GetMethod("set_ReturnObj")); 94                 } 95             } 96             #endregion 97  98             //catch 99             il.BeginCatchBlock(typeof(Exception));100             var exception = il.DeclareLocal(typeof(Exception));101             il.Emit(OpCodes.Stloc, exception);102 103             #region 初始化ExceptionContext104             var exceptionContentType = typeof(ExceptionContext);105             var exceptionContent = il.DeclareLocal(exceptionContentType);106             var exceptionContentCtor = exceptionContentType.GetConstructor(Type.EmptyTypes);107             il.Emit(OpCodes.Newobj, exceptionContentCtor);108             il.Emit(OpCodes.Stloc, exceptionContent);109             #endregion110 111             #region 給ExceptionContext的參數值屬性ParameterArgs,MethodInfo,ExceptionInfo,賦值112             il.Emit(OpCodes.Ldloc, exceptionContent);113             il.Emit(OpCodes.Ldloc_0);114             il.Emit(OpCodes.Call, exceptionContentType.GetMethod("set_ParameterArgs"));115 116             il.Emit(OpCodes.Ldloc, exceptionContent);117             il.Emit(OpCodes.Ldloc, methodInfo);118             il.Emit(OpCodes.Call, exceptionContentType.GetMethod("set_MethodInfo"));119 120             il.Emit(OpCodes.Ldloc, exceptionContent);121             il.Emit(OpCodes.Ldloc, exception);122             il.Emit(OpCodes.Call, exceptionContentType.GetMethod("set_ExceptionInfo"));123             #endregion124 125             #region 調用切面對象的InvokingException方法126             for (int i = 0; i < attrLen; i++)127             {128                 il.Emit(OpCodes.Ldloc, lbs[i]);129                 il.Emit(OpCodes.Ldloc, exceptionContent);130                 il.Emit(OpCodes.Callvirt, invokingExceptionMethods[i]);131                 il.Emit(OpCodes.Nop);132             }133             #endregion134             //try end135             il.EndExceptionBlock();136 137             #region 調用切面對象的AfterInvoke方法138             for (int i = 0; i < attrLen; i++)139             {140                 il.Emit(OpCodes.Ldloc, lbs[i]);141                 il.Emit(OpCodes.Ldloc, context);142                 il.Emit(OpCodes.Callvirt, endInvokeMethods[i]);143                 il.Emit(OpCodes.Nop);144             }145             #endregion146 147             if (!isReturnVoid)148                 il.Emit(OpCodes.Ldloc, result);149 150             //返回151             il.Emit(OpCodes.Ret);
繼承類模式

該種方式,建立在使用base.XXXMethod(arg1,arg2,...)模式來調用被Aop的對象的業務方法,關鍵點是使用BeginExceptionBlock(),BeginCatchBlock(typeof(Exception)),EndExceptionBlock();來動態創建try catch代碼塊,進行異常處理。

四、實現接口模式

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 任丘市| 资溪县| 宁津县| 开原市| 松桃| 运城市| 三亚市| 聂拉木县| 普兰店市| 鄂尔多斯市| 吕梁市| 临泽县| 雅安市| 东乡县| 安塞县| 左云县| 罗田县| 眉山市| 安仁县| 晴隆县| 合川市| 永登县| 崇文区| 乌鲁木齐县| 汾阳市| 保康县| 昌黎县| 六盘水市| 桃江县| 龙州县| 曲周县| 集贤县| 台江县| 峨边| 宁强县| 迁西县| 泸州市| 通化市| 沧源| 晋州市| 咸丰县|