在.Net中关于AOP的实现(三)

 

2、 不同的aspect使用不同的Attribute。此时可以为这些Attribute定义一个共同的抽象基类AOPAttribute:

[AttributeUsage(AttributeTargets.Class)]

     public abstract class AOPAttribute:ContextAttribute

     {

          public AOPAttribute()

              : base("AOP")

          {

          }

 

          public sealed override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)

          {

              ctorMsg.ContextProperties.Add(GetAOPProperty());

          }

 

          protected abstract AOPProperty GetAOPProperty();         

     }

注:我将GetPropertiesForNewContext()方法sealed,目的是不需要其子类在重写该方法。

 

继承AOPAttribute类的子类只需要重写GetAOPProperty()方法即可。但在为OrderManager类定义Attribute的时候,需注意其顺序。如以下的顺序:

[AuthorizationAOP]

[AuthenticationAOP]

public class OrderManager{}

此时,AuthorizationAOPAttribute在前,AuthenticationAOPAttribute在后。如果以Decorator的角度来看,对被装饰的方法,AuthorizationAOPAttribute在内,AuthenticationAOPAttribute在外。

考虑到aspect的应用,有的方法需要多个aspect,有的则只需要单个aspect,所以,第二个方案更佳。

 

五、AOP实例

接下来,我通过一个实例,介绍AOP的具体实现。假定我们要设计一个计算器,它能提供加法和减法功能。我们希望,在计算过程中,能够通过日志记录整个计算过程及其结果,同时需要监测其运算性能。该例中,核心业务是加法和减法,而公共的业务则是日志与监测功能。根据前面对AOP的分析,这两个功能应为我们整个系统需要剥离出来的“方面”。

 

我们已经拥有了一个AOP实现机制,以及核心的类库,包括AOPSink、AOPProperty、AOPAttribute三个抽象基类。现在,我们分别为日志aspect和监测aspect,定义相应的Sink、Property、Attribute。

 

首先是日志aspect:

LogAOPSink.cs:

using System;

using System.Runtime.Remoting.Messaging;

using Wayfarer.AOP;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for LogAOPSink.

     ///

     public class LogAOPSink:AOPSink

     {

          public LogAOPSink(IMessageSink nextSink):base(nextSink)

          {

             

          }

 

          protected override void AddAllBeforeAOPHandles()

          {

               AddBeforeAOPHandle("ADD",new BeforeAOPHandle(Before_Log));

              AddBeforeAOPHandle("SUBSTRACT",new BeforeAOPHandle(Before_Log));

          }

 

          protected override void AddAllAfterAOPHandles()

          {

              AddAfterAOPHandle("ADD",new AfterAOPHandle(After_Log));

              AddAfterAOPHandle("SUBSTRACT",new AfterAOPHandle(After_Log));

          }

 

          private void Before_Log(IMethodCallMessage callMsg)

          {            

              if (callMsg == null)

              {

                   return;

              }            

                        Console.WriteLine("{0}({1},{2})",callMsg.MethodName,callMsg.GetArg(0),callMsg.GetArg(1));

          }

 

          private void After_Log(IMethodReturnMessage replyMsg)

          {            

              if (replyMsg == null)

              {

                   return;

              }            

              Console.WriteLine("Result is {0}",replyMsg.ReturnValue);          

          }

 

     }

}

 

LogAOPProperty.cs

using System;

using Wayfarer.AOP;

using System.Runtime.Remoting.Messaging;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for LogAOPProperty.

     ///

     public class LogAOPProperty:AOPProperty

     {

          protected override IMessageSink CreateSink(IMessageSink nextSink)

          {

              return new LogAOPSink(nextSink);

          }

 

          protected override string GetName()

          {

              return "LogAOP";

          }

     }

}

LogAOPAttribute.cs:

using System;

using System.Runtime.Remoting.Activation;

using System.Runtime.Remoting.Contexts;

using Wayfarer.AOP;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for LogAOPAttribute.

     ///

     [AttributeUsage(AttributeTargets.Class)]

     public class LogAOPAttribute:AOPAttribute

     {

          protected override AOPProperty GetAOPProperty()

          {

              return new LogAOPProperty();

          }

    

     }

}

 

然后再定义监测aspect:

MonitorAOPSink.cs:

using System;

using System.Runtime.Remoting.Messaging;

using Wayfarer.AOP;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for MonitorAOPSink.

     ///

     public class MonitorAOPSink:AOPSink

     {

          public MonitorAOPSink(IMessageSink nextSink):base(nextSink)

          {

             

          }

 

          protected override void AddAllBeforeAOPHandles()

          {

              AddBeforeAOPHandle("ADD",new BeforeAOPHandle(Before_Monitor));

              AddBeforeAOPHandle("SUBSTRACT",new BeforeAOPHandle(Before_Monitor));

          }

          protected override void AddAllAfterAOPHandles()

          {

              AddAfterAOPHandle("ADD",new AfterAOPHandle(After_Monitor));

              AddAfterAOPHandle("SUBSTRACT",new AfterAOPHandle(After_Monitor));

          }

 

          private void Before_Monitor(IMethodCallMessage callMsg)

          {            

              if (callMsg == null)

              {

                   return;

              }

              Console.WriteLine("Before {0} at {1}",callMsg.MethodName,DateTime.Now);

          }

          private void After_Monitor(IMethodReturnMessage replyMsg)

          {            

              if (replyMsg == null)

              {

                   return;

              }

              Console.WriteLine("After {0} at {1}",replyMsg.MethodName,DateTime.Now);

          }

     }

}

MonitorAOPProperty.cs:

using System;

using Wayfarer.AOP;

using System.Runtime.Remoting.Messaging;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for MonitorAOPProperty.

     ///

     public class MonitorAOPProperty:AOPProperty

     {

          public MonitorAOPProperty()

          {

              //

              // TODO: Add constructor logic here

              //

          }

 

          protected override IMessageSink CreateSink(IMessageSink nextSink)

          {

              return new MonitorAOPSink(nextSink);

          }

 

          protected override string GetName()

          {

              return "MonitorAOP";

          }

     }

}

MonitorAOPAttribute.cs:

using System;

using System.Runtime.Remoting.Activation;

using System.Runtime.Remoting.Contexts;

using Wayfarer.AOP;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for MonitorAOPAttribute.

     ///

     [AttributeUsage(AttributeTargets.Class)]

     public class MonitorAOPAttribute:AOPAttribute

     {

          protected override AOPProperty GetAOPProperty()

          {

              return new MonitorAOPProperty();

          }

     }

}

注意在这两个方面中,各自的Property的Name必须是唯一的。

现在,可以定义计算器类。

Calculator.cs:

using System;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for Calculator.

     ///

     [MonitorAOP]

     [LogAOP]

     public class Calculator:ContextBoundObject

     {

          public int Add(int x,int y)

          {

              return x + y;

          }

 

          public int Substract(int x,int y)

          {

              return x - y;

          }

     }

}

需要注意的是Calculator类必须继承ContextBoundObject类。

最后,我们写一个控制台程序来执行Calculator:

Program.cs:

using System;

 

namespace Wayfarer.AOPSample

{

     ///

     /// Summary description for Class1.

     ///

     class Program

     {

          ///

          /// The main entry point for the application.

          ///

          [STAThread]

          static void Main(string[] args)

          {

              Calculator cal = new Calculator();

              cal.Add(3,5);

              cal.Substract(3,5);

              Console.ReadLine();

          }

     }

}

运行结果如下:

aopresult.GIF

六、结论

在.Net平台下采用动态代理技术实现AOP,其原理并不复杂,而.Net Framework也提供了足够的技术来实现它。如果再结合好的设计模式,提供一个基本的AOP框架,将大大地简化开发人员处理“aspect”的工作。当然,本文虽然提供了实现AOP的实例,但其架构的设计还远远不能达到企业级的要求,如在稳定性、可扩展性上还需经过进一步的测试与改善。例如我们可以通过配置文件的形式,来配置方法与方面之间的映射。同时,由于采用了动态代理,在性能上还期待改进。

 

使用动态代理技术实现AOP,对实现AOP的类有一个限制,就是必须派生于ContextBoundObject类,这对于单继承语言来说,确实是一个比较致命的缺陷。所谓“仁者见仁,智者见智”,这就需要根据项目的情况,做出正确的抉择了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值