.NET中对AOP的研究(系列二)

.自定义AOP的实现方式

1、使用ContextAttribute和ContextBoundObject来对对象的方法进行拦截。关于ContextAttribute的具体使用方法,读者可以参考MSDN等相关资料。

2、使用Proxy模式。这也是本文的实现方法。

 

二、直接上代码

 

1、首先定义了抽象类AspectObject,所有需要AOP管理的类,都必须从这个类继承下来。这个类的定义如下:

    public abstract class AspectObject : ContextBoundObject

   之所以定义这个类,并且让它继承ContextBoundObject,其原因是因为,.Net能够拦截任何直接从ContextBoundObject派生的类(包括子类的子类);另外定义成abstract,目的是为了将来可能的扩充性,我们据此可以对其在运行时刻的行为做出一些自定义的控制,请看如下代码:

      public class BusinessOperation: AspectObject

     {

         ……

     }

 

2、AspectManagedAttribute

     这是一个非常关键的类,其作用是拦截类的构造函数。如前所述,当你在执行诸如:

     BusinessOperation business = new BusinessOperation();

     你实际上得到的不是BusinessOperation,而是BusinessOperation的一个代理,正因为如此,我们才能够在执行这个对象的方法的时候,把他们拦截下来,插入我们自己的代码。 

   此类代码如下:

    [AttributeUsage(AttributeTargets.Class)]  //由于这个特性允许标识在类上,所在需要加上[AttributeUsage(AttributeTargets.Class)]
    [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.Infrastructure)]
    public class AspectManagedAttribute : ProxyAttribute

     {

         private bool aspectManaged;
        private string[] aspectsType;

          public AspectManagedAttribute(bool AspectManaged, string AspectType)
        {
            aspectManaged = AspectManaged;
            aspectsType = AspectType.Split(',');
        }

           public override MarshalByRefObject CreateInstance(Type serverType)
        { 
            MarshalByRefObject mobj= base.CreateInstance(serverType);
            if(aspectManaged) //aspectManaged指明该类是否接受Aspect管理
            {
                RealProxy realProxy = new AspectProxy(serverType, mobj, aspectsType);
                MarshalByRefObject retobj = realProxy.GetTransparentProxy() as MarshalByRefObject;
                return retobj;
            }
            else
            {
                return mobj;
            }
        }

     }

     重写ProxyAttribute的方法:MarshalByRefObject CreateInstance(Type serverType)。根据不同的AspectManagedType创建不同的自定义代理类。

     当我们拦截构造函数的时候,就会执行这个方法,在这里,我们可以对被拦截的构造函数的类进行一些处理,生成被实例化的类的代理。

     此类定义完之后,在BusinessOperation类上就可加入此属性类

    [AspectManaged(true, "AspectClient.SecondAspect, AspectClient.SecurityAspect")]
    public class BusinessOperation: AspectObject

    {

    }

3、AspectProxy

    需要继承RealProxy,它提供代理的基本功能。

    当被代理的某个对象的方法执行时,就会被代理所拦截,代理会执行Invoke方法。

    public class AspectProxy : RealProxy    
   {

        MarshalByRefObject target = null;

        string[] _aspectsType = null;


        /// <summary>
        /// 默认构造函数
        /// </summary>

        public AspectProxy() : base()
        {


        }


            /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="myType">被代理的类的类型</param>

        public AspectProxy(Type type) : base(type)
        {


        }


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="myType">被代理的类的类型</param>
        /// <param name="obj">被代理的对象</param>
        public AspectProxy(Type type, MarshalByRefObject obj, string[] aspectsType) : base(type)
        {
            target = obj;

            _aspectsType = aspectsType;
        }

        public override IMessage Invoke(IMessage message)

        {

            IMessage Msg;

            PreProcess(message); //被拦截方法执行前进行处理

            if(message is IConstructionCallMessage//如果message是构造函数

            {

                IConstructionCallMessage constructCallMsg = message as IConstructionCallMessage;

                RemotingServices.GetRealProxy(target).InitializeServerObject(constructCallMsg);

                ObjRef oRef = RemotingServices.Marshal(target);
                RemotingServices.Unmarshal(oRef);

                Msg = EnterpriseServicesHelper.CreateConstructionReturnMessage(constructCallMsg ,(MarshalByRefObject)this.GetTransparentProxy());

            }

           else if(message is IMethodCallMessage)

            {

                IMethodCallMessage callMsg = message as IMethodCallMessage;

                retMsg = RemotingServices.ExecuteMessage(target, callMsg );

            }

            PostProcess(msg);  //被拦截方法执行后进行处理

           return Msg;

        }

        /// <summary>
        /// 被拦截方法执行前进行处理,AspectActionPosition是个枚举包含三个元素,Befor,After,Both
        /// </summary>
        /// <param name="message">IMessage,包含有关方法调用的信息</param>

        private void PreProcess(IMessage message)
        {
           IAspect[] aspectBefore = AspectsManager.GetAspect(message, AspectActionPosition.Before, _aspectsType);
           if((aspectBefore != null) && (aspectBefore.Length > 0))
           {
              for(int i = 0; i < aspectBefore.Length; i++)
              {
                 aspectBefore[i].PreProcess(message);
              }
            }
         }

        /// <summary>
        /// 被拦截方法执行后进行处理
        /// </summary>
        /// <param name="message">IMessage,包含有关方法调用的信息</param>

        private void PostProcess(IMessage message)
        {
           IAspect[] aspectAfter = AspectsManager.GetAspect(message, AspectActionPosition.After, _aspectsType);
           if((aspectAfter != null) && (aspectAfter.Length > 0))
           {
              for(int i = 0; i < aspectBefore.Length; i++)
              {
                 aspectAfter[i].PostProcess(message);
              }
            }
         }
   

     }

4、辅助的接口和类

   上面一些主要类都已介绍完毕.另外还一些辅助的接口和类

    public interface IAspect
    {
        /// <summary>
        /// 在被拦截的方法执行前执行的方法
        /// </summary>
        /// <param name="Message">IMessage,包含有关方法调用的信息</param>
        void PreProcess(IMessage Message);


        /// <summary>
        /// 在被拦截的方法执行后执行的方法
        /// </summary>
        /// <param name="Message">IMessage,包含有关方法调用的信息</param>

        void PostProcess(IMessage Message);
    }

   所有的拦截业务都要继承这个接口(当然这个接口可以再扩展).

   例如定义一个SecurityAspect类

    public class SecurityAspect : IAspect

    {

        public void PreProcess()

        {

            if(!Security.CheckRight(......))

             {

                 throw new SecurityException("你没有权限!");

             }

        }

        public void PostProcess()

        {

            ………

        }

     }

        

    public class AspectsManager   //Aspects管理类

    {

        //这里面主要用到的是GetAspect,返回IAspect数组.

        //根据Config文件中的配置以及[AspectManaged(true, "AspectClient.SecondAspect, AspectClient.SecurityAspect")]定义获取

        //每个需要拦截的业务类的IAspect集合.

    }

 

    下面是配置文件中的配置:

   <Websharp.Aspects>
        <Aspect type="AspectClient.SecurityAspect,AspectClient" deploy-model="Singleton" pointcut-type="Method" action-position="Before" match="*,*" />
        <Aspect type="AspectClient.LogAspect,AspectClient" deploy-model="Singleton" pointcut-type="Method" action-position="After" match="*,*" />
   </Websharp.Aspects>

 

 

   自定义AOP的实现方式就差不多写完了,可能个人技术水平,只能写到这样了.希望有问题请给出指正,大家共同探讨.

 

转载于:https://www.cnblogs.com/tangzhenjie/archive/2013/06/06/3118482.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值