在看.net core 源码的管道模型中间件(middleware)部分,觉得这个流程组装,思路挺好的,于是就分享给大家。本次代码实现就直接我之前写的动态代理实现aop的基础上改的,就不另起炉灶了,主要思路就是运用委托。对委托不理解的可留言,我写一篇委托的常规使用方式,以及底层原理(编译器)的文章
没看过上一章的,我这里大家给贴一下地址:.net core 实现动态代理做aop(面向切面编程)
定义好我们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">结果</param> void beforeaction(object?[]? args, object? result); }
这里只定义一个基类特性类,继承标记接口,用于设置共通配置,且利于后面反射查找
[attributeusage(attributetargets.class)] internal class bainterceptattribute : attribute, iinterceptor { }
只需要继承.net core 原生dispatchproxy类,重写相关业务代码
编写一个我们自己的create方法(),这两个参数为了后面调用目标类储备的,方法实现就只需要调用dispatchproxy类的create()
internal class dynamicproxy<t> : dispatchproxy { public t decorated { get; t; }//目标类 public ienumerable<iinterceptoraction> interceptors { get; t; } // aop动作 /// <summary> /// 创建代理实例 /// </summary> /// <param name="decorated">代理的接口类型</param> /// <param name="afteraction">方法执行前执行的事件</param> /// <param name="beforeaction">方法执行后执行的事件</param> /// <returns></returns> public t create(t decorated, ienumerable<iinterceptor> interceptors) { object proxy = 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)).lect(c=>c as iinterceptoraction); return (t)proxy; }
这个就是需要实现我们自己的业务了,大家看注释应该就能看懂个大概蚂蚁屋了,目前这里只处理了iinterceptoraction接口逻辑,比如异常、异步等等,自己可按需实现。而流程组装的精髓就三步
1.不直接去执行targetmethod.invoke(),而是把它放到委托里面。
2.定义asmbleaction()方法来组装流程,方法里面也不执行方法,也是返回一个执行方法的委托。
3.循环事先在create()方法存储的特性实例,调用asmbleaction()方法组装流程,这样就达到俄罗斯套娃的效果了。
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.rever()) { action = asmbleaction(action, c); } //执行组装好的流程 var result = action?.invoke(args); //如果方法有异常抛出异常 if (exception != null) { throw exception; } return result; } private func<青春之歌诗歌;object?[]?, object?>? asmbleaction(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}"); } } }
工厂用于专门来为我们创建代理类,逻辑很简单,后续大家也可以按需编写,目前逻辑就是利用反射获取目标类的特性,把参数组装起来。
internal class proxyfactory { /// <summary> /// 创建代理实例 /// </summary> /// <param name="decorated">代理的接口类型</param> /// <returns></returns> public static t create<t>() { var decorated = rvicehelp.getrvice<t>(); var type = decorated.gettype(); var interceptattribut = type.getcustomattributes<bainterceptattribute>(); //创建代理类 var proxy = new dynamicproxy<t>().create(decorated, interceptattribut); return proxy; 指责英语 } }
这个是为了使得我们全局只用一个作用域的ioc容器
public static class rvicehelp { public static irviceprovider? rviceprovider { get; t; } public static void buildrviceprovider(irvicecollection rvicecollection) { //构建容器 rviceprovider = rvicecollection.buildrviceprovider(); } public static t getrvice<t>(type rvicetype) { return (t)rviceprovider.getrvice(rvicetype); } public static t getrvice<t>() { return rviceprovider.getrvice<t>(); } }
写两个特性实现,继承基类特性,实现action接口逻辑,测试两个特性随意调换位置进行组装流程
internal class aoptest1attribut : bainterceptattribute, 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 : bainterceptattribute, 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}"); } }
写一个简单的测试服务,就比如两个整数相加,然后标记上我们写的aop特性
internal interface itestrvice { public int add(int a, int b); } [aoptest2attribut] [aoptest1attribut] internal class testrvice : itestrvice { public int add(int a, int b) { console.writeline($"正在执行--》add({a},{b})"); //throw new exception("方法执行--》测试异常"); return a + b; } }
1.把服务注册到ioc
2.调用创建代理类的工厂
3.调用测试服务函数:.add(1, 2)
irvicecollection rvicecollection = new rvicecollection();rvicecollection.addtransient<itestrvice, testrvice>();rvicehelp.buildrviceprovider(rvicecollection);//用工厂获取代理实例var s = proxyfactory.create<itestrvice>();var sum = s.add(1, 2);
aop1->aop2->add(a,b)
aop2->aop1->add(a,b)
代码上传至gitee,aop流程组装分支:https://gitee.com/luoxiangbao/dynamic-proxy.git
到此这篇关于.net core 利用委托实现动态流程组装的文章就介绍到这了,更多相关.net core动态流程组装内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 13:48:27,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/9b5e3ef249e507790c522f9988196e3d.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:.NET Core 使用委托实现动态流程组装的思路详解.doc
本文 PDF 下载地址:.NET Core 使用委托实现动态流程组装的思路详解.pdf
留言与评论(共有 0 条评论) |