首页 > 学院 > 开发设计 > 正文

自己实现简单的AOP(二)引入Attribute为方法指定增强对象

2019-11-14 15:50:33
字体:
来源:转载
供稿:网友

话续前文 : 自己实现简单的AOP(一)简介 

 

在前一篇文章中,对AOP的实现方式做了一个简单介绍。接下来,引入Attribute 为方法指定增强对象,由此实现一个简单的AOP。

注意:指定的是增强对象,“对象”,也就是说Attribute标记,标记的其实是一个对象。由此、使用多态便可轻松实现增强的扩展。

 

自定义的Attribute 

    /// <summary>    /// 为方法标记指定的增强对象    /// <para>指定的增强,可通过代理 DelayPRoxy 织入</para>    /// </summary>    [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]    public sealed class AdviceAttribute : Attribute    {        /// <summary>        /// 增强对象        /// </summary>        public AdviceAbstract Advice { get; private set; }        /// <summary>        /// 使用指定类型的默认增强对象        /// <para>如果类型为空 则不使用任何增强</para>        /// </summary>        /// <param name="type"></param>        public AdviceAttribute(Type type)            : this(type, string.Empty)        {        }        /// <summary>        /// 使用公有静态方法名初始化指定类型的增强对象        /// <para>如果类型为空 则不使用任何增强</para>        /// </summary>        /// <param name="type">类型</param>        /// <param name="methodName">        /// 公有静态方法名        /// <para>如果方法名为空,调用默认构造函数</para>        /// </param>        public AdviceAttribute(Type type, string methodName)        {            // 如果类型为空 则不使用任何增强            if (type == null)            {                this.Advice = null;                return;            }            if (string.IsNullOrWhiteSpace(methodName))            {                this.Advice = Activator.CreateInstance(type) as AdviceAbstract;                return;            }            this.Advice = type.InvokeMember(                methodName,                System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public                | System.Reflection.BindingFlags.Static,                null, null, null) as AdviceAbstract;        }        #region 以下两种方式效果不是很好,不推荐使用,故 构造函数私有化        /// <summary>        /// 使用参数列表初始化指定类型的增强对象        /// </summary>        /// <param name="type">类型</param>        /// <param name="objs">参数列表</param>        private AdviceAttribute(Type type, params object[] objs)        {            this.Advice = Activator.CreateInstance(type, objs) as AdviceAbstract;        }        /// <summary>        /// 使用命名参数初始化指定类型的增强对象        /// </summary>        /// <param name="namedParameter">        /// 以 冒号 和 分号 分割的形参的命名参数列表        /// <para>支持的数据类型有:string, int, bool 及 可通过静态方法Parse 反序列化的类型</para>        /// </param>        /// <param name="type"></param>        private AdviceAttribute(string namedParameter, Type type)        {            this.Advice = ReflectionUtil.InvokeConstructor(type, namedParameter) as AdviceAbstract;        }        #endregion    }
Attribute

 

增强的抽象类 和 自定义的增强

    /// <summary>    /// 抽象的增强类    /// </summary>    public abstract class AdviceAbstract    {        public abstract IMessage Invoke(MarshalByRefObject target, IMethodCallMessage callMessage);    }    public class MyAdvice : AdviceAbstract    {        public override IMessage Invoke(MarshalByRefObject target, IMethodCallMessage callMessage)        {            this.BeforeInvoke(target);            IMessage message = DelayProxyUtil.InvokeBeProxy(target, callMessage);            this.AfterInvoke(target);            return message;        }        protected virtual void BeforeInvoke(MarshalByRefObject target)        {            Console.WriteLine("Before");        }        protected virtual void AfterInvoke(MarshalByRefObject target)        {            Console.WriteLine("After");        }    }
Advice

 

有了如上的两个组件,再借助代理类 DelayProxy<T>,将增强织入,简单的AOP就已经初具原形了。

    /// <summary>    /// 支持泛型、支持延迟初始化的代理类, 可为 MarshalByRefObject 的子类型提供代理    /// <para>在执行代理的过程中,获取 AdviceAttribute 所指定的增强,并织入该增强</para>    /// </summary>    public class DelayProxy<T> : RealProxy where T : MarshalByRefObject    {        private static object objLock = new object();        /// <summary>        /// 被代理的对象        /// </summary>        private T target;        /// <summary>        /// 是否延迟初始化        /// <para>True:延迟, False: 不延迟</para>        /// </summary>        private readonly bool delay;        public DelayProxy(T target, bool delay)            : base(typeof(T))        {            this.target = target;            this.delay = delay;        }        /// <summary>        /// 调用被代理对象        /// <para>支持 out ref 参数</para>        /// </summary>        /// <param name="msg"></param>        /// <returns></returns>        public override IMessage Invoke(IMessage msg)        {            if (this.delay && this.target == null)            {                lock (objLock)                {                    if (this.delay && this.target == null)                    {                        T instance = Activator.CreateInstance(typeof(T)) as T;                        // 自动装配属性                        // 为属性对象启用代理,并延迟初始化被代理的对象                        // DelayProxyUtil.AutowiredProperties(instance);                        this.target = instance;                    }                }            }            IMethodCallMessage callMessage = (IMethodCallMessage)msg;            AdviceAttribute attri = ReflectionUtil.GetCustomAttribute<AdviceAttribute>(callMessage.MethodBase);            if (attri != null && attri.Advice != null)            {                return attri.Advice.Invoke(this.target, callMessage);            }            return DelayProxyUtil.InvokeBeProxy(this.target, callMessage);        }    }
DelayProxy

 

源码(MVC4的项目 没有packages文件夹):http://files.VEVb.com/files/08shiyan/AOPDemo.zip 

该源码中还实现了被代理对象的延迟初始化。

 

未完待续...

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表