前言
aop即是面向切面编程,众多Aop框架里Castle是最为人所知的,另外还有死去的Spring.NET,当然,.NET Core社区新秀AspectCore在性能与功能上都非常优秀,已经逐渐被社区推崇和有越来越多的人使用。感谢柠檬同学的礼物!
如果大家出于自身需求或者学习,想实现一个Aop,是不是觉得一来就要使用Emit去做?最近我了解到了System.Reflection.DispatchProxy这个corefx类库,已经实现了动态代理功能。
1|1System.Reflection.DispatchProxy
下面演示一下它的使用方法:
class Program { static void Main(string[] args) { //创建代理类,并把SampleProxy作为拦截器注入 var sampleProxy = (targetInterface)SampleProxy.Create<targetInterface, SampleProxy>(); //执行接口方法 sampleProxy.Write("here is invoke by proxy"); } } //需要被生成代理实例的接口 public interface targetInterface { //这个方法会被代理类实现 void Write(string writesomeshing); } public class SampleProxy : DispatchProxy { /// <summary> /// 拦截调用 /// </summary> /// <param name="method">所拦截的方法信息</param> /// <param name="parameters">所拦截方法被传入的参数指</param> /// <returns></returns> protected override object Invoke(MethodInfo targetMethod, object[] args) { Console.WriteLine(args[0]); return null; } }
2|0改造成一款简易AOP
2|1为什么?
System.Reflection.DispatchProxy只有一个Api,就是objecct Create<T,TProxy>() where TProxy:DispatchProxy,约束了只能传入泛型参数,并不能从方法传入类型,这就会带来很多问题。而更可气的是,给官方提了issue之后,还是不给增加这个api……
2|2改造方法
幸好,在那个issue下,issue作者提供了一个解决方案,就是用反射来构造这个泛型方法。我还在这基础上,封装了一下,加入了传入拦截器实例和传入拦截器构造方法参数的功能。
/// <summary> /// 拦截器接口 /// </summary> public interface IInterceptor { /// <summary> /// 拦截器调用 /// </summary> /// <param name="target">代理实例</param> /// <param name="method">所拦截的方法</param> /// <param name="parameters">所拦截方法传入的参数值</param> /// <returns>返回值会传递给方法返回值</returns> object Intercept(object target, MethodInfo method, object[] parameters); }
拦截器要实现这个接口,下面是对DispatchProxy的封装,实现更多创建代理实例的方法
public class ProxyGenerator : DispatchProxy { private IInterceptor interceptor { get; set; } /// <summary> /// 创建代理实例 /// </summary> /// <param name="targetType">所要代理的接口类型</param> /// <param name="interceptor">拦截器</param> /// <returns>代理实例</returns> public static object Create(Type targetType, IInterceptor interceptor) { object proxy = GetProxy(targetType); ((ProxyGenerator)proxy).CreateInstance(interceptor); return proxy; } /// <summary> /// 创建代理实例 /// </summary> /// <param name="targetType">所要代理的接口类型</param> /// <param name="interceptorType">拦截器类型</param> /// <param name="parameters">拦截器构造函数参数值</param> /// <returns>代理实例</returns> public static object Create(Type targetType, Type interceptorType, params object[] parameters) { object proxy = GetProxy(targetType); ((ProxyGenerator)proxy).CreateInstance(interceptorType, parameters); return proxy; } /// <summary> /// 创建代理实例 TTarget:所要代理的接口类型 TInterceptor:拦截器类型 /// </summary> /// <param name="parameters">拦截器构造函数参数值</param> /// <returns>代理实例</returns> public static TTarget Create<TTarget, TInterceptor>(params object[] parameters) where TInterceptor : IInterceptor { var proxy = GetProxy(typeof(TTarget)); ((ProxyGenerator)proxy).CreateInstance(typeof(TInterceptor), parameters); return (TTarget)proxy; } private static object GetProxy(Type targetType) { var callexp = Expression.Call(typeof(DispatchProxy), nameof(DispatchProxy.Create), new[] { targetType, typeof(ProxyGenerator) }); return Expression.Lambda<Func<object>>(callexp).Compile()(); } private void CreateInstance(Type interceptorType, object[] parameters) { var ctorParams = parameters.Select(x => x.GetType()).ToArray(); var paramsExp = parameters.Select(x => Expression.Constant(x)); var newExp = Expression.New(interceptorType.GetConstructor(ctorParams), paramsExp); this.interceptor = Expression.Lambda<Func<IInterceptor>>(newExp).Compile()(); } private void CreateInstance(IInterceptor interceptor) { this.interceptor = interceptor; } protected override object Invoke(MethodInfo method, object[] parameters) { return this.interceptor.Intercept(method, parameters); } }
2|3使用方法
class Program { static void Main(string[] args) { var poxy1 = (targetInterface)ProxyGenerator.Create(typeof(targetInterface), new SampleProxy("coreproxy1")); poxy1.Write("here was invoked"); //---> "here was invoked by coreproxy1" var poxy2 = (targetInterface)ProxyGenerator.Create(typeof(targetInterface), typeof(SampleProxy), "coreproxy2"); poxy2.Write("here was invoked"); //---> "here was invoked by coreproxy2" var poxy3 = ProxyGenerator.Create<targetInterface, SampleProxy>("coreproxy3"); poxy3.Write("here was invoked"); //---> "here was invoked by coreproxy3" } } public class SampleProxy : IInterceptor { private string proxyName { get; } public SampleProxy(string name) { this.proxyName = name; } public object Intercept(MethodInfo method, object[] parameters) { Console.WriteLine(parameters[0] + " by " + proxyName); return null; } } public interface targetInterface { void Write(string writesome); }
3|0总结
总结一下就是,微软爸爸给我们的这个轮子还是即轻便又很好用的。
本文的实例代码可以在我的github上找到:https://github.com/ElderJames/CoreProxy
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对小牛知识库的支持。
本文向大家介绍Java核心库实现简单的AOP,包括了Java核心库实现简单的AOP的使用技巧和注意事项,需要的朋友参考一下 Spring是一个十分火热开源框架,而AOP(面向切面编程)则是Spring最重要的概念之一,为了更好的理解和学习AOP的思想,使用核心库来实现一次不失为一个好方法。 首先介绍一下AOP的概念,AOP(Aspect Oriented Programming),即面向切
本文向大家介绍node实现爬虫的几种简易方式,包括了node实现爬虫的几种简易方式的使用技巧和注意事项,需要的朋友参考一下 说到爬虫大家可能会觉得很NB的东西,可以爬小电影,羞羞图,没错就是这样的。在node爬虫方面,我也是个新人,这篇文章主要是给大家分享几种实现node 爬虫的方式。第一种方式,采用node,js中的 superagent+request + cheerio。cheerio是必须
本文向大家介绍仿照Element-ui实现一个简易的$message方法,包括了仿照Element-ui实现一个简易的$message方法的使用技巧和注意事项,需要的朋友参考一下 前言 在需要对用户进行提示时,有时会遇到这种场景:使用模态框提示太过硬核,使用toast提示又太轻了,这时候可以选择使用页面顶部滑下的消息提示。本文仿照element-ui的实现一个类似$message的方法。 思路梳理
本文向大家介绍ios实现简易队列,包括了ios实现简易队列的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了ios实现简易队列的具体代码,供大家参考,具体内容如下 满足一些特殊需求 接口部分(队列支持需求) 实现方法 测试 结果 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍iOS实现简易钟表,包括了iOS实现简易钟表的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了iOS实现简易钟表的具体代码,供大家参考,具体内容如下 效果图: 注意:表盘是一个UIImageView控件,设置image为表盘图片 核心代码: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍Qt实现简易时钟,包括了Qt实现简易时钟的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了Qt实现简易时钟展示的具体代码,供大家参考,具体内容如下 一、效果展示 简单实现时钟(圆盘+QLCDNumber),大小刻度,数字等。 二、实现 .pro .h .cpp 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。