动态代理配合rpc技术调用远程服务,不用关注细节的实现,让程序就像在本地调用以用。
因此动态代理在微服务系统中是不可或缺的一个技术。网上看到大部分案例都是通过反射自己实现,且相当复杂。编写和调试相当不易,我这里提供里一种简便的方式来实现动态代理。
1、创建我们的空白.netcore项目
通过vs2017轻易的创建出一个.netcore项目
2、编写Startup.cs文件
默认Startup 没有构造函数,自行添加构造函数,带有 IConfiguration 参数的,用于获取项目配置,但我们的示例中未使用配置
在ConfigureServices 配置日志模块,目前core更新的很快,日志的配置方式和原来又很大出入,最新的配置方式如下
添加路由过滤器,监控一个地址,用于调用我们的测试代码。netcore默认没有UTF8的编码方式,所以要先解决UTF8编码问题,否则将在输出中文时候乱码。
这里注意 Map 内部传递了参数 applicationBuilder ,千万不要 使用Configure(IApplicationBuilder app, IHostingEnvironment env ) 中的app参数,否则每次请求api/health时候都将调用这个中间件(app.Run会短路期后边所有的中间件),
3、代理
netcore 已经为我们完成了一些工作,提供了DispatchProxy 这个类
这个类提供了一个实例方法,一个静态方法:
Invoke(MethodInfo targetMethod, object[] args) (注解1)
Create<T, TProxy>()(注解2)
Create 创建代理的实例对象,实例对象在调用方法时候会自动执行Invoke
首先我们创建一个动态代理类 ProxyDecorator<T>:DispatchProxy 需要继承DispatchProxy 。
在DispatchProxy 的静态方法 Create<T, TProxy>()中要求 TProxy : DispatchProxy
ProxyDecorator 重写 DispatchProxy的虚方法invoke
我们可以在ProxyDecorator 类中添加一些其他方法,比如:异常处理,MethodInfo执行前后的处理。
重点要讲一下
ProxyDecorator 中需要传递一个 T类型的变量 decorated 。
因为 DispatchProxy.Create<T, ProxyDecorator<T>>(); 会创建一个新的T的实例对象 ,这个对象是代理对象实例,我们将 decorated 绑定到这个代理实例上
接下来这个代理实例在执行T类型的任何方法时候都会用到 decorated,因为 [decorated] 会被传给 targetMethod.Invoke(decorated, args) (targetMethod 来自注解1) ,invoke相当于执行
这样说的不是很明白,我们直接看代码
代码比较简单,相信大家都看的懂,关键的代码和核心的系统代码已经加粗和加加粗+红 标注出来了
DispatchProxy<T> 类中有两种创建代理实例的方法
我们看一下第一种比较简单的创建方法
代码中 UserService 和 IUserService 是一个class和interface 自己实现即可 ,随便写一个接口,并用类实现,任何一个方法就行,下面只是演示调用方法时候会执行什么,这个方法本身在岩石中并不重要。
由于ProxyDecorator 中并未注入相关事件,所以我们在调用 user.GetUserName(222) 时候看不到任何特别的输出。下面我们演示一个相对复杂的调用方式。
IUserService user = serviceProxy.Create(userService, beforeEvent, afterEvent); 在创建代理实例时候传递了beforEvent 和 afterEvent,这两个事件处理函数是我们在业务中定义的void beforeEvent(MethodInfo methodInfo, object[] arges){System.Diagnostics.Debug.WriteLine("方法执行前");}
void afterEvent(MethodInfo methodInfo, object[] arges){System.Diagnostics.Debug.WriteLine("执行后的事件");}
在代理实例执行接口的任何方法的时候都会执行 beforeEvent,和 afterEvent 这两个事件(请参考Invoke(MethodInfo targetMethod, object[] args) 方法的实现)
在我们的示例中将会在vs的 输出 面板中看到
方法执行前
“方法输出的值”
执行后事件
我们看下运行效果图:
这是 user.GetUserName(222) 的运行结果
控制台输出结果
原文链接:https://www.cnblogs.com/netqq/p/11452374.html
.NET社区新闻,深度好文,欢迎访问文章汇总 ;