目录
引言接下来进入正题2.定义特性3.编写生成代理类的逻辑3.1 编写创建代理方法3.2 重写Invoke方法4.定义一个工厂5.定义ServiceHelp6.测试6.1 编程AOP实现6.2 编写测试服务6.3 调用6.4 效果图引言
在看.NET Core 源码的管道模型中间件(Middleware)部分,觉得这个流程组装,思路挺好的,于是就分享给大家。本次代码实现就直接我之前写的动态代理实现AOP的基础上改的,就不另起炉灶了,主要思路就是运用委托。对委托不理解的可留言,我写一篇委托的常规使用方式,以及底层原理(编译器)的文章

没看过上一章的,我这里大家给贴一下地址:.NET Core 实现动态代理做AOP(面向切面编程)
接下来进入正题
1.定义接口IInterceptor
定义好我们AOP需要实现的接口,不同职责可以定义不同接口,大家根据实际情况划分
internal interface IInterceptor { } internal interface IInterceptorAction : IInterceptor { /// <summary> /// 执行之前 /// </summary> /// <param name="args">参数</param> void AfterAction(object?[]? args); /// <summary> /// 执行之后 /// </summary> /// <param name="args">参数</param> /// <param name="result">able<IInterceptor> interceptors) { object prkKfqmoxy = Create<T, DynamicProxy<T>>(); // 调用DispatchProxy 的Create 创建一个代理实例 DynamicProxy<T> proxyDecorator = (DynamicProxy<T>)proxy; proxyDecorator.Decorated = decorated; proxyDecorator.Interceptors = interceptors.Where(c=>c.GetType().GetInterface(typeof(IInterceptorAction).Name) == typeof(IInterceptorAction)).Select(c=>c as IInterceptorAction); return (T)proxy; }3.2 重写Invoke方法
这个就是需要实现我们自己的业务了,大家看注释应该就能看懂个大概了,目前这里只处理了IInterceptorAction接口逻辑,比如异常、异步等等,自己可按需实现。而流程组装的精髓就三步
1.不直接去执行targetMethod.Invoke(),而是把它放到委托里面。
2.定义AssembleAction()方法来组装流程,方法里面也不执行方法,也是返回一个执行方法的委托。
3.循环事先在Create()方法存储的特性实例,调用AssembleAction()方法组装流程,这样就达到俄罗斯套娃的效果了。
protected override object? Invoke(MethodInfo? targetMethod, object?[]? args) { Exception exception = null;//由委托捕获变量,用来存储异常 Func<object?[]?, object?> action = (args) => { try { return targetMethod?.Invoke(Decorated, args); } catch (Exception ex)//捕获异常,不影响AOP继续执行 { exception = ex; } return null; }; //进行倒序,使其按照由外置内的流程执行 foreach (var c in Interceptors.Reverse()) { action = AssembleAction(action, c); } //执行组装好的流程 var result = action?.Invoke(args); //如果方法有异常抛出异常 if (exception != null) { throw exception; } return result; } private Func<object?[]?, object?>? AssembleAction(Func<object?[]?, object?>? action, IInterceptorAction c) { return (args) => { //执行之前的动作 AfterAction(c.AfterAction, args); var result = action?.Invoke(args); //执行之后的动作 BeforeAction(c.BeforeAction, args, result); return result; }; } private void AfterAction(Action<object?[]?> action, object?[]? args) { try { action(args); } catch (Exception ex) { Console.WriteLine($"执行之前异常:{ex.Message},{ex.StackTrace}"); } } private void BeforeAction(Action<object?[]?, object?> action, object?[]? args, object? result) { try { action(args, result); } catch (Exception ex) { Console.WriteLine($"执行之后异常:{ex.Message},{ex.StackTrace}"); } } }4.定义一个工厂
工厂用于专门来为我们创建代理类,逻辑很简单,后续大家也可以按需编写,目前逻辑就是www.easck.com利用反射获取目标类的特性,把参数组装起来。
internal class ProxyFactory { /// <summary> /// 创建代理实例 /// </summary> /// <param name="decorated">代理的接口类型</param> /// <returns></returns> public static T Create<T>() { var decorated = ServiceHelp.GetService<T>(); var type = decorated.GetType(); var interceptAttribut = type.GetCustomAttributes<BaseInterceptAttribute>(); //创建代理类 var proxy = new DynamicProxy<T>().Create(decorated, interceptAttribut); return proxy; } }5.定义ServiceHelp
这个是为了使得我们全局只用一个作用域的IOC容器
public static class ServiceHelp { public static IServiceProvider? serviceProvider { get; set; } public static void BuildServiceProvider(IServiceCollection serviceCollection) { //构建容器 serviceProvider = serviceCollection.BuildServiceProvider(); } public static T GetService<T>(Type serviceType) { return (T)serviceProvider.GetService(serviceType); } public static T GetService<T>() { return serviceProvider.GetService<T>(); } }6.测试
6.1 编程AOP实现
写两个特性实现,继承基类特性,实现Action接口逻辑,测试两个特性随意调换位置进行组装流程
internal class AOPTest1Attribut : BaseInterceptAttribute, IInterceptorAction { public void AfterAction(object?[]? args) { Console.WriteLine($"AOP1方法执行之前,args:{args[0] + "," + args[1]}"); // throw new Exception("异常测试(异常,但依然不能影响程序执行)"); } public void BeforeAction(object?[]? args, object? result) { Console.WriteLine($"AOP1方法执行之后,result:{result}"); } } internal class AOPTest2Attribut : BaseInterceptAttribute, IInterceptorAction { public void AfterAction(object?[]? args) { Console.WriteLine($"AOP2方法执行之前,args:{args[0] + "," + args[1]}"); } public void BeforeAction(object?[]? args, object? result) { Console.WriteLine($"AOP2方法执行之后,result:{result}"); } }6.2 编写测试服务
写一个简单的测试服务,就比如两个整数相加,然后标记上我们写的AOP特性
internal interface ITestService { public int Add(int a, int b); } [AOPTest2Attribut] [AOPTest1Attribut] internal class TestService : ITestService { public int Add(int a, int b) { Console.WriteLine($"正在执行--》Add({a},{b})"); //throw new Exception("方法执行--》测试异常"); return a + b; } }6.3 调用
1.把服务注册到IOC
2.调用创建代理类的工厂
3.调用测试服务函数:.Add(1, 2)
IServiceCollection serviceCollection = new ServiceCollection();serviceCollection.AddTransient<ITestService, TestService>();ServiceHelp.BuildServiceProvider(serviceCollection);//用工厂获取代理实例var s = ProxyFactory.Create<ITestService>();var sum = s.Add(1, 2);
6.4 效果图
AOP1->AOP2->Add(a,b)

AOP2->AOP1->Add(a,b)

代码上传至gitee,AOP流程组装分支:https://gitee.com/luoxiangbao/dynamic-proxy.git








