首页 > 作文

.NET Core 使用委托实现动态流程组装的思路详解

更新时间:2023-04-04 13:48:29 阅读: 评论:0

目录
引言接下来进入正题 2.定义特性3.编写生成代理类的逻辑3.1 编写创建代理方法3.2 重写invoke方法4.定义一个工厂5.定义rvicehelp6.测试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">结果</param>        void beforeaction(object?[]? args, object? result);    }

2.定义特性

这里只定义一个基类特性类,继承标记接口,用于设置共通配置,且利于后面反射查找

 [attributeusage(attributetargets.class)]    internal class bainterceptattribute : attribute, iinterceptor    {    }

3.编写生成代理类的逻辑

只需要继承.net core 原生dispatchproxy类,重写相关业务代码

3.1 编写创建代理方法

编写一个我们自己的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;        }

3.2 重写invoke方法

这个就是需要实现我们自己的业务了,大家看注释应该就能看懂个大概蚂蚁屋了,目前这里只处理了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}");            }        }    }

4.定义一个工厂

工厂用于专门来为我们创建代理类,逻辑很简单,后续大家也可以按需编写,目前逻辑就是利用反射获取目标类的特性,把参数组装起来。

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;       指责英语 }    }

5.定义rvicehelp

这个是为了使得我们全局只用一个作用域的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>();        }    }

6.测试

6.1 编程aop实现

写两个特性实现,继承基类特性,实现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}");        }    }

6.2 编写测试服务

写一个简单的测试服务,就比如两个整数相加,然后标记上我们写的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;        }    }

6.3 调用

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);

6.4 效果图

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 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图