当前位置 : 主页 > 编程语言 > 其它开发 >

使用DispatchProxy抽象类 实现自定义AOP 支持异步拦截

来源:互联网 收集:自由互联 发布时间:2022-06-30
首先您需要了解什么是AOP 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,

首先您需要了解什么是AOP

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是众多框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

主要功能 日志记录,性能统计,安全控制,事务处理,异常处理等等。 主要意图 将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

一、继承 DispatchProxy 抽象类 重写 Invoke 方法

 1 /// <summary>
 2     /// 动态代理
 3     /// </summary>
 4     /// <typeparam name="T"></typeparam>
 5     internal class DynamicProxy<T> : DispatchProxy
 6     {
 7         /// <summary>
 8         /// 目标
 9         /// </summary>
10         public object _target;
11 
12         /// <summary>
13         ///14         /// </summary>
15         public Action<MethodInfo, object[]> _before;
16 
17         /// <summary>
18         ///19         /// </summary>
20         public Action<MethodInfo, object[]> _after;
21 
22         /// <summary>
23         /// 调用
24         /// </summary>
25         /// <param name="targetMethod">目标方法</param>
26         /// <param name="args">参数</param>
27         /// <returns></returns>
28         protected override object Invoke(MethodInfo targetMethod, object[] args)
29         {
30             var flag = targetMethod.IsDefined(typeof(AopAttribute), true);
31             object result = null;
32             if (flag)
33             {
34                 _before?.Invoke(targetMethod, args);
35                 if (targetMethod.ReturnType.FullName.Equals("System.Threading.Tasks.Task"))
36                 {
37                     var task = targetMethod.Invoke(_target, args) as dynamic;
38                     if (targetMethod.ReturnType.GenericTypeArguments.Length == 0)
39                     {
40                         task.Wait();
41                         result = task;
42                     }
43                     else
44                     {
45                         result = Task.FromResult(task.Result);
46                     }
47                 }
48                 else
49                 {
50                     result = targetMethod.Invoke(_target, args);
51                 }
52                 _after?.Invoke(targetMethod, args);
53             }
54             else
55             {
56                 result = targetMethod.Invoke(_target, args);
57             }
58             return result;
59         }
60     }

二、创建工厂类 管理对象  Action<MethodInfo, object[]> before = null, Action<MethodInfo, object[]> after = null 该参数 可以使用 接口或者 抽象类 实现多态 我这里直接用委托 可根据自己需求自定义 逻辑差不多

 1 /// <summary>
 2     /// 动态代理工厂
 3     /// </summary>
 4     public static class DynamicProxyFactory
 5     {
 6 
 7         /// <summary>
 8         /// 缓存
 9         /// </summary>
10         private static readonly ConcurrentDictionary<string, object> _cache;
11 
12         /// <summary>
13         /// 构造方法
14         /// </summary>
15         static DynamicProxyFactory()
16         {
17             _cache = new ConcurrentDictionary<string, object>();
18         }
19 
20         /// <summary>
21         /// 创建
22         /// </summary>
23         /// <typeparam name="T"></typeparam>
24         /// <param name="target">目标</param>
25         /// <param name="before"></param>
26         /// <param name="after"></param>
27         /// <returns></returns>
28         public static T Create<T>(object target, Action<MethodInfo, object[]> before = null, Action<MethodInfo, object[]> after = null)
29         {
30             var key = typeof(T).GUID.ToString();
31             var obj = _cache.GetOrAdd(key, k =>
32             {
33                 return DispatchProxy.Create<T, DynamicProxy<T>>();
34             });
35             var proxy = obj as DynamicProxy<T>;
36             proxy._target = target;
37             proxy._before = before;
38             proxy._after = after;
39             obj = proxy;
40             return (T)obj;
41         }
42     }

 

上一篇:通过 hosts文件配置本地域名
下一篇:没有了
网友评论