frameWork

2022-11-07 17:00:05 浏览数 (1)

引言

       何为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的实现,接下来我们看代码,

代码语言:javascript复制
   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();
        }
    }

使用方式

代码语言:javascript复制
            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方法。

代码语言:javascript复制
 /// <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的一个读写分离,实现了读写分离的两种方式的一个案例。

0 人点赞