利用Attribute实现Aop

Aop“面向切面编程”,与OOP“面向对象编程”一样是一种编程思路。个人理解:在不改变原有逻辑的基础上,注入其他行为。

基础代码(仿MVC拦截器实现)

 

namespace HGL.Toolkit.Aop
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public sealed class AopAttribute : ContextAttribute, IContributeObjectSink
    {
        public AopAttribute() : base("Aop") { }

        //实现IContributeObjectSink接口当中的消息接收器接口
        public IMessageSink GetObjectSink(MarshalByRefObject obj, IMessageSink next)
        {
            return new AopProxy(next);
        }
    }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class AopMethodAttribute : Attribute
    {
        /// <summary>
        /// 方法执行之前,执行代码
        /// </summary>
        public virtual bool OnMethodExecuting(System.Web.HttpContext context)
        {
            return true;
        }

        /// <summary>
        /// 方法执行之后,执行代码
        /// </summary>
        public virtual bool OnMethodExecuted(System.Web.HttpContext context)
        {
            return true;
        }
    }
}

namespace HGL.Toolkit.Aop
{
    public sealed class AopProxy : IMessageSink
    {
        //下一个接收器
        private IMessageSink nextSink;

        public IMessageSink NextSink
        {
            get { return nextSink; }
        }

        public AopProxy(IMessageSink nextSink)
        {
            this.nextSink = nextSink;
        }

        //同步处理方法
        public IMessage SyncProcessMessage(IMessage msg)
        {
            IMessage retMsg = null;

            //方法调用消息接口
            IMethodCallMessage call = msg as IMethodCallMessage;

            var attributes = Attribute.GetCustomAttributes(call.MethodBase, typeof(AopMethodAttribute));

            //如果被调用的方法没打AopMethodAttribute标签
            if (call == null || attributes.Count() == 0)
            {
                retMsg = nextSink.SyncProcessMessage(msg);
            }
            //如果打了AopMethodAttribute标签
            else
            {
                foreach (var attribute in attributes)
                {
                    var obj = attribute.GetType();

                    var executing = obj.GetMethod("OnMethodExecuting");
                    if (executing != null)
                    {
                        var context=System.Web.HttpContext.Current;
                        executing.Invoke(attribute, new object[] { context });
                    }
                }

                retMsg = nextSink.SyncProcessMessage(msg);

                foreach (var attribute in attributes)
                {
                    var obj = attribute.GetType();

                    var executed = obj.GetMethod("OnMethodExecuted");
                    if (executed != null)
                    {
                        var context = System.Web.HttpContext.Current;
                        executed.Invoke(attribute, new object[] { context });
                    }
                }
            }

            return retMsg;
        }

        //异步处理方法(不需要)
        public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
        {
            return null;
        }
    }
}

 

 使用注意:

1.使用到Aop的类必须继承ContextBoundObject
2.使用到Aop的方法存在的类必须添加[Aop]特性
3.哪个方法需要实现Aop,就给那个方法添加[AopMethod]特性

AopMethod未实现任何业务逻辑,使用者需要重写该attribute

/// <summary>
/// 方法执行之前,执行代码
/// </summary>
public virtual bool OnMethodExecuting()
{
    return true;
}

/// <summary>
/// 方法执行之后,执行代码
/// </summary>
public virtual bool OnMethodExecuted()
{
    return true;
}

 待续......(将执行前和执行后的方法使用代理委托机制,实现二次开发)

 

posted @ 2014-12-01 16:13  细数青春  阅读(367)  评论(0编辑  收藏  举报