用代理技术实现简单的AOP框架

在许多的实现AOP框架的技术中,不管是静态织入还是动态织入,关键点在于拦截方法,并在方法中加入预处理和后处理。而实现方法的拦截的一个简单办法就是 把类的实例委托给类的真实代理(RealProxy).这样以来,方法的调用都会被转换成消息(IMessage),同时该消息作为参数被送到真实代理的 Invoke方法。所以我们相应地改写Invoke方法,加入预处理和后处理也就OK了。

根据这个思路,可以给出一个简单的代码实现:
一,定义方法拦截的接口
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Messaging;

namespace LYG.Share.Interface
{
    public interface IInterceptor
    {
        void PreProcess(IMessage requestMSG);
        void PostProcess(IMessage requestMSG, IMessage returnMSG);
    }
}
二,真实代理的实现
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Activation;
using System.Runtime.Remoting.Services;
using LYG.Share .Interface ;

namespace LYG.Share.AOP.Proxies
{
    public abstract class AspectProxy : RealProxy, IInterceptor
    {

        private MarshalByRefObject _target = null;

        public AspectProxy()
            : base()
        {
        }
        public AspectProxy(Type serverType)
            : base(serverType)
        {
        }
             
        public void InitProxyTarget(MarshalByRefObject target)
        {
            this._target = target;
        }
        public override IMessage Invoke(IMessage msg)
        {
            bool useInterception = false;
            IMethodCallMessage invoke = (IMethodCallMessage)msg;

            foreach (InterceptionAttribute attr in invoke.MethodBase.GetCustomAttributes(false))
            {
                if (attr != null)
                {
                    if (attr.UseInterception)
                    {
                        useInterception = true;
                        break;
                    }
                }
            }

            if (useInterception)
            {
                this.PreProcess(msg);
            }

            IConstructionCallMessage ctorInvoke = invoke as IConstructionCallMessage;
            if (ctorInvoke != null)
            {
                RealProxy default_proxy = RemotingServices.GetRealProxy(this._target );
                default_proxy.InitializeServerObject(ctorInvoke);
                MarshalByRefObject tp = (MarshalByRefObject)this.GetTransparentProxy();
                return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctorInvoke, tp);
            }

            IMethodReturnMessage returnMSG = RemotingServices.ExecuteMessage(this._target, invoke);
            if (useInterception)
            {
                this.PostProcess(msg, returnMSG);
            }
            return returnMSG;
        }

        #region implemente IInterceptor
        public abstract void PreProcess(IMessage requestMSG);
        public abstract void PostProcess(IMessage requestMSG, IMessage returnMSG);
        #endregion      
    }
}
三,代理特性的实现
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting.Proxies;
using LYG.Share .Interface ;

namespace LYG.Share.AOP.Proxies
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false,Inherited=false)]
    public class AspectAttribute : ProxyAttribute
    {
        private Type _proxyType = null;
        public AspectAttribute(Type proxyType)
            :base()
        {
            _proxyType = proxyType;
        }
        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            MarshalByRefObject mobj = base.CreateInstance(serverType);
            AspectProxy proxyInstance = (AspectProxy)Activator.CreateInstance(_proxyType, new object[] { serverType});
            proxyInstance.InitProxyTarget(mobj);
            return proxyInstance.GetTransparentProxy() as MarshalByRefObject;
        }
    }
}
四,方法拦截特性的实现
using System;
using System.Collections.Generic;
using System.Text;

namespace LYG.Share.AOP.Proxies
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class InterceptionAttribute:Attribute
    {
        private bool _useInterception = false;

        public InterceptionAttribute(bool useInterception)
        {
            this._useInterception = useInterception;
        }

        public bool UseInterception
        {
            get
            {
                return this._useInterception;
            }
        }
    }
}
五,测试用例
 public class AspectServiceProxy : AspectProxy
    {
      
        public AspectServiceProxy(Type serverType)
            : base(serverType)
        {
        }
     
        public override void PreProcess(IMessage requestMSG)
        {
          //对拦截方法的预处理          
        }
        public override void PostProcess(IMessage requestMSG, IMessage returnMSG)
        {
            //对拦截方法的后处理
        }
      
    }

[Aspect(typeof(AspectServiceProxy))]
    public class AspectServiceClass : ContextBoundObject
    {
        private int _value = 0;
        public AspectServiceClass(int value)
        {
            _value = value;
        }
        [Interception(true)]
        public int Add(int value)
        {
            _value += value;
            return _value;
        }    
      
    }


....
       AspectServiceClass asc=new AspectServiceClass(5);
       asc.Add(6);
......

总结

     这个AOP框架的主要优点在于当我们要为一个已经写好的类的方法植入新的处理时,我们不需要对该类的方法实现做修改。只需要实现一个类的拦截代理(如 AspectServiceProxy),并对类加[Aspect(typeof(AspectServiceProxy))]特性,对要被拦截的方法加 [Interception(true)]特性。最重要的是被拦截的类的调用方式没有任何的改变,AspectServiceClass asc=new AspectServiceClass(5)这样的调用可能散布在系统的许多地方。如果被经过AOP改造后的类的调用方式发生改变那么就必须修改系统中每 一个调用改类的地方,这样造成的代码的变动可能不是我们所期望的,也于AOP理念的初衷是不相符合的(实现上许多的AOP框架都存在这个遗憾)。当然这个 AOP框架的缺点也是显而易见的,首先,所有要被代理的类都必须继承自ContextBoundObject,而事实上许多的类可能要实现其他的继承,一 个愚蠢的办法就是把ContextBoundObject作为系统中所有类的基类。其次,就是不能实现方法的多重拦截。
posted @ 2007-06-25 00:21  Nathan.Liu  阅读(2859)  评论(12编辑  收藏  举报