一、前言

  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 初始化ExceptionContext
104             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             #endregion
110 
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             #endregion
124 
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             #endregion
134             //try end
135             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             #endregion
146 
147             if (!isReturnVoid)
148                 il.Emit(OpCodes.Ldloc, result);
149 
150             //返回
151             il.Emit(OpCodes.Ret);
继承类模式

相关文章:

  • 2021-04-30
  • 2021-10-03
  • 2022-02-21
  • 2022-03-11
  • 2021-11-20
  • 2021-04-06
  • 2021-11-06
  • 2022-03-07
猜你喜欢
  • 2021-11-28
  • 2021-10-22
  • 2022-03-06
  • 2021-07-14
  • 2021-11-20
  • 2021-11-22
  • 2021-05-10
相关资源
相似解决方案