Net 实现自定义Aop
引言
何为AOP,在软件开发中,总是听到这个AOP这个词语,但是何为AOP呢,AOP全称是Aspect Oriented Programming,中文译为面向切面编程,什么意思呢,即我们的应用程序在运行的时候,我们在调用方法的时候,我们当前这个父类方法需要调用下面某个类的方法,等待这个方法给我们返回一个结果或者不返回,那这样的过程我们可以抽象的理解为自上而下,然后在自下而上,那AOP的概念我们就可以理解为在这个自上而下,和自下而上的过程中我们,我们实现了一层拦截,横插了一个处理程序,用来实现对方法和方法之间调用的一个拦截,可以实现自上而下,经过我们的AOP层面的代码,以及自下而上的时候 经过我们的AOP代码,在这个AOP层面,我们可以实现对程序的日志记录,异常处理,参数验证等等的一些常规操作。
实现方式
Aop的实现方式,大体是分为两个版本一个是不同框架下的实现方式,不同平台就是Framework下面的实现方式,还有一种是Core下面的实现方式,这里我们主要讲这两种,第二个实现方式下面是两个通用的实现方式,一种是基于IL的形式去实现,还有一种是基于内存的形式的实现,这里不太对这两种进行过多的讲解,后续会写一个使用IL去实现AOP的代码,这里主要讲FrameWork和Core框架下如何实现AOP代理的两种比较简单的方法。
frameWork
在framework的框架下,可以使用RealProxy类来实现静态代理的的aop,需要自己去继承RealProxy这个类,然后实现Invoke的抽象方法,即可实现Aop的实现,接下来我们看代码,
public class DynamicProxy<T> : RealProxy { public T Instance = default; public IInterceptor Interceptor; public DynamicProxy():base(typeof(T)) { } public T GetInstance< Target, TInterceptor>() where TInterceptor: IInterceptor where Target: class,T { var result = this.GetTransparentProxy(); Instance = Activator.CreateInstance<Target>() ; Interceptor = Activator.CreateInstance<TInterceptor>(); return (T)result; } public override IMessage Invoke(IMessage msg) { var methodMsg = msg as IMethodCallMessage; try { if (methodMsg!=null) { var methodInfo = methodMsg.MethodBase as MethodInfo; if (Interceptor != null) { Interceptor.BeforeEvent(methodMsg.MethodBase, methodMsg.InArgs); } var result= methodMsg.MethodBase.Invoke(Instance, methodMsg.InArgs); if (Interceptor != null) { Interceptor.AfterEvent(methodMsg.MethodBase, result); } return new ReturnMessage(result, null, 0, methodMsg.LogicalCallContext, methodMsg); } } catch (Exception ex) { if (Interceptor != null) { Interceptor.ExceptionEvent(ex, methodMsg.MethodBase); } } return new ReturnMessage(null, null, 0, methodMsg.LogicalCallContext, methodMsg); } } public interface IBase { string GetName(); } public class BaseModel : IBase { public string GetName() { return Guid.NewGuid().ToString(); } }
使用方式
var proxy = new DynamicProxy<IBase>(); var ins=proxy.GetInstance<BaseModel,TestInterceptor>(); var result=ins.GetName();
我们在需要代理的对象的时候,我们传入了这个对象的继承的类型,在构造函数调用了RealProxy的构造方法传入我们需要代理的类型Type,然后在这里我写了一个创建对象以及设置拦截器的一个方法,可以看到在这个方法里,我们获取到了这个泛型T的静态代理的对象,这是我们要返回给上一层的,此处是我们创建的代理对象,在下面我们有创建了一个这个Target的对象,很多人就有些疑惑了,为什么同一类型的对象我们需要创建两次呢,这里呢是因为,如果我们同意的去使用这个静态的代理作为我们的Instance的话,那在Invoke方法里,我们调用我们调用的GetName的方法的Invoke的时候,会造成一个死循环的一个操作,就是不停的去GetName,也就不停止的走我们重写的Invoke的方法,这里,就起到了一个隔离作用,简单来说,就是上层对象需要将一个类型代理,走到我们的GetInstance方法中去,我们给他返回这个代理的对象,然后我们类内部同时有一个未被代理的对象在创建出来,这样我们的类有一个没被代理的实例,这样在代理的对象调用GetName的时候就可以走到我们的Invoke的方法中去,我们在执行GetName的方法时候我们使用Instance实例去承载我们所调用的方法,获取到结果之后在返回到调用的上方去,就类似于桥接的方式,我调用了A的GetName方法,但是在代理层面有一个B的实例,实际上我们是调用的是B的GetName的方法,而且GetInstance方法里面的返回必须是代理的对象,不然是不会走到Invoke方法中去,从而没办法实现拦截。
可以看到我们在GetInstance的时候我们也创建了我们的拦截器的实例,再看我们的Invoke方法,我们在方法的执行前,执行后,以及异常的时候我们分别调用了拦截器的BeforeEvent,AfterEvent以及ExceptionEvent方法,分别去传入我们的执行前后,异常等信息。
Net Core
在net core框架出来之后呢,代理方面也是有了一个改动,在fw版本下可以使用RealProxy实现AOP的功能,但是由于其性能方面以及其他方面的原因,core并不支持RealProxy,以及Core是不支持fw版本中的Remoting的,所以Core是以另一种方式支持代理去实现AOP的功能,其性能以及使用起来大大简化了RealProxy的功能,并且如果非面向抽象开发的前提下,RealProxy代理还需要继承MarshalByRefObject这个抽象接口,导致代理的对象调用方法的时候,过于依赖MarshalByRefObject,.方法名称的时候是可以看到基类的方法,这对我们来说很不友好,所以Core版本引入了DispatchProxy的类来实现代理,这个类同RealProxy一样是个抽象类,也必须实现Invoke方法。
/// <summary> /// Aop Proxy /// </summary> public class DynamicProxy : DispatchProxy { /// <summary> /// 执行方法接口 /// </summary> private IInterceptor interceptor { get; set; } /// <summary> /// 具体类型 /// </summary> private object service { get; set; } /// <summary> /// 创建代理 /// </summary> /// <param name="targetType"></param> /// <param name="interceptor"></param> /// <param name="serviceParameter"></param> /// <returns></returns> public static object Create(Type targetType, IInterceptor interceptor, object[] serviceParameter = null) { object proxy = GetProxy(targetType); ((DynamicProxy)proxy).CreateInstance(interceptor); ((DynamicProxy)proxy).service = CreateServiceInstance(targetType, serviceParameter); return proxy; } /// <summary> /// 创建代理,targetType为类,interceptorType继承IInterceptor,serviceParameter为targetType为类构造函数的参数,parameters为interceptorType构造函数参数 /// </summary> /// <param name="targetType"></param> /// <param name="interceptorType"></param> /// <param name="serviceParameter"></param> /// <param name="parameters"></param> /// <returns></returns> public static object Create(Type targetType, Type interceptorType, object[] serviceParameter = null, params object[] parameters) { object proxy = GetProxy(targetType); ((DynamicProxy)proxy).CreateInstance(interceptorType, parameters); ((DynamicProxy)proxy).service = CreateServiceInstance(targetType, serviceParameter); return proxy; } /// <summary> /// tIService为接口,tService实现tIService接口,intercer继承IInterceptor,serviceParameter为targetType为类构造函数的参数,parameters为interceptorType构造函数参数 /// </summary> /// <param name="tIService"></param> /// <param name="tService"></param> /// <param name="intercer"></param> /// <param name="serviceParameter"></param> /// <param name="parameters"></param> /// <returns></returns> public static object Create(Type tIService, Type tService, Type intercer, object[] serviceParameter = null, params object[] parameters) { var proxy = GetProxy(tIService); ((DynamicProxy)proxy).CreateInstance(intercer, parameters); ((DynamicProxy)proxy).service = CreateServiceInstance(tService, serviceParameter); return proxy; } /// <summary> /// TTarget为接口,tService实现tIService接口,TInterceptor继承IInterceptor,serviceParameter为targetType为类构造函数的参数,parameters为interceptorType构造函数参数 /// </summary> /// <typeparam name="TTarget"></typeparam> /// <typeparam name="TService"></typeparam> /// <typeparam name="TInterceptor"></typeparam> /// <param name="serviceParameter"></param> /// <param name="parameters"></param> /// <returns></returns> public static TTarget Create<TTarget, TService, TInterceptor>(object[] serviceParameter = null, params object[] parameters) where TInterceptor : IInterceptor where TService : TTarget { var proxy = GetProxy(typeof(TTarget)); ((DynamicProxy)proxy).CreateInstance(typeof(TInterceptor), parameters); ((DynamicProxy)proxy).service = CreateServiceInstance(typeof(TService), serviceParameter); return (TTarget)proxy; } /// <summary> /// 创建指定类型对象,servicePara构造函数参数 /// </summary> /// <param name="type"></param> /// <param name="servicePara"></param> /// <returns></returns> private static object CreateServiceInstance(Type type, params object[] servicePara) { return Activator.CreateInstance(type, servicePara); } /// <summary> /// 创建代理,表达式执行泛型方法性能优于MakeGenericMethod /// </summary> /// <param name="targetType"></param> /// <returns></returns> private static object GetProxy(Type targetType) { var callexp = Expression.Call(typeof(DispatchProxy), nameof(DispatchProxy.Create), new[] { targetType, typeof(DynamicProxy) }); return Expression.Lambda<Func<object>>(callexp).Compile().Invoke(); } /// <summary> /// 创建Aop具体实现类,表达式性能优于反射性能 /// </summary> /// <param name="interceptorType"></param> /// <param name="parameters"></param> 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()(); } /// <summary> /// 赋值 /// </summary> /// <param name="interceptor"></param> private void CreateInstance(IInterceptor interceptor) { this.interceptor = interceptor; } /// <summary> /// 实现Invole方法 /// </summary> /// <param name="method"></param> /// <param name="parameters"></param> /// <returns></returns> protected override object Invoke(MethodInfo method, object[] parameters) { if (method == null) throw new Exception("无效的方法"); try { if (this.interceptor != null) { this.interceptor.BeforeEvent(method, parameters); } object result = method.Invoke(service, parameters); if (method.ReturnType.BaseType == typeof(Task)) { var resultTask = result as Task; if (resultTask != null) { resultTask.ContinueWith(task => { if (task.Exception != null) { if (interceptor != null) { var resultEx = this.interceptor.ExceptionEvent(task.Exception.InnerException ?? task.Exception, method); result = resultEx; } } else { object taskResult = task.GetType().GetProperty("Result").GetValue(task); if (interceptor != null) { this.interceptor.AfterEvent(method, taskResult); } } }).ConfigureAwait(false).GetAwaiter().GetResult(); return result; } } else { try { if (interceptor != null) { this.interceptor.AfterEvent(method, result); return result; } } catch (Exception ex) { if (interceptor != null) { return this.interceptor.ExceptionEvent(ex, method); } else { return null; } } } return null; } catch (Exception ex) { if (interceptor != null) { return this.interceptor.ExceptionEvent(ex, method); } else { return null; } } } }
从Invoke方法来看,直接成了我们所需要调用的方法的信息,以及对应的参数,那同样的,这个类实际上也有一些缺陷就是,Dispatch这个类里面有一个Create的方法可以去为我们生成代理类,但是这个Create方法,如果你传入的Type是具体的class,Create方法是会报错的,因为Create方法不支持具体的类型,而是对应的父类接口类型,至于抽象类,我没试过,有兴趣的小伙伴可以在后面自己试一下调用Create方法传入的是抽象类的前提下是否可以代理成功。
同样的,在RealProxy中我们可以记录日志,异常,执行前,执行后等操作,在这个Invoke里面,我们同样可以,这便是我在FrameWork以及Core中实现Aop的两种方式。
IL的形式去实现
之前的博客中,我有写过IL方面的合集,那实际上通过使用IL我们也可以实现一个动态代理去实现AOP的功能,目前的话,我是没有写相关的代码,但是IL的话 大体思路是这样的,我们去动态创建DLL以及Module,以及去创建一个Type继承我们需要代理的类或者接口,然后我们需要去用IL去实现父类的那几个方法,然后我们讲我们创建的类型去返回给依赖方,依赖方在调用方法的时候,会进入到我们用IL写的代码中去,在IL构造的方法中,我们可以直接return代理对象的同名同类型的方法,从而实现AOP的功能,可能在这里说的比较抽象,后面我会写一篇使用IL去实现AOP的功能代码,到时候会在博客中一一讲解。
内存的形式
实际上,内存的形式目前我是没有写过,但是在网上有看到过相关的代码,其是利用反射我们获取到方法的MethodHandle然后通过内存的形式,然后通过内存Copy实现的AOP,相关代码目前我已找不到,因为这种方式需要的功力深厚,目前我是达不到的,如果后续研究明白,再来一一分析,分享给大家,针对于第四种这种实现方式,大家可以参考一下这个博客https://www.cnblogs.com/Bob-wei/p/7345574.html,这种方式去实现AOP的手段,目前我是整不明白的。下一篇博客的话,我可能会写一些c#中跨进程通讯的各种手段。
RealProxy版本:http://121.43.235.192:8082/s/Sb5xs7rH88CECn6
DispatchProxy版本:http://121.43.235.192:8082/s/xpKFAWc6rpb7nd6
DispatchProxy版本中,我是实现了一个EFCore的一个读写分离,实现了读写分离的两种方式的一个案例。
大家如果有不懂的地方,可以看如果自己加的net群里有叫四川观察的基本上就是我,或者可以直接添加群聊可以找到我,在此,谢谢各位大佬的支持,后续依旧会带来更多的干货