SqlCenter项目中实现了基于.Net Remoting 透明代理的AOP框架,取得了非常不错的效果.
本文通过验证组件的实现,简单介绍下SqlCenter中AOP 的思想和运用:)

验证组件,为了实现对类属性等的约束和判断的轻量级组件.  比如Filed实体中Name不能为空这个约束.对这个约束的判断就可以通过我们的验证组件实现. 

如果Field属性Name不能为空这个约束,用常规方法实现,则如下:

SqlCenter中的AOP实现public string Name

        这里还是一个最为简单的约束.如果更加复杂呢?同时同种约束的实体很多呢?我们的代码就需要不断的重复.有没有点小孩尿布的味道了?  是的, 我们应该有更好的方案! 
       这个时候,AOP的作用派上了用场.本文假设你对AOP基础理论和对以下知识都有了解:元数据、Attribute、.Net Remoting的代理技术.

从这里你也深入的学习到这些知识:http://www.brucezhang.com/?p=33

下面就我能理解的 "基于AOP的验证组件" 做点分析:)

先看看实现了AOP验证的代码是什么样子的:

SqlCenter中的AOP实现[AspectAttribute]
SqlCenter中的AOP实现
public class Field : ContextBoundObject 

是不是非常优雅?代码非常清晰,琐碎的约束性判断代码一点都没有,也就一点没有影响核心关注了:)

SqlCenter中的AOP是基于.Net Remoting 代理实现的.

上面代码告诉我们,需要自定义了一个ProxyAttribute,命名为AspectAttribute:

SqlCenter中的AOP实现[AttributeUsage(AttributeTargets.Class)]
SqlCenter中的AOP实现
public sealed class AspectAttribute : ProxyAttribute
 

通过MSDN可以知道:

将当前属性应用于需要自定义代理的类型。可以使用 ProxyAttribute 类来截获 new(在 Visual Basic 中为 New)语句,方法是:从 ProxyAttribute 派生,并将该属性置于 ContextBoundObject 的子级上。(不支持将代理属性置于 MarshalByRefObject 的子级上。)

在实现AspectAttribut中有个AspectProxy。这个是? 是的这个就是我们需要透明代理对象。它的实现:

 

SqlCenter中的AOP实现class AspectProxy : System.Runtime.Remoting.Proxies.RealProxy 
SqlCenter中的AOP实现


通过这样的实现,一个AOP组件框架就出来了! (由于是基于.Net Remoting 的实现,很多烦琐的实现都被屏蔽了,也不需要你理解IL代码了,当然认识本质还是需要的 :)

那么如何具体的实现一个组件呢?其实也很简单,只要实现了下面这个interface就算搞定了!

public interface IInterceptor
{
void Init(object target);
void Begin(IMethodCallMessage call);
void End(ref IMethodReturnMessage message);
void Catch(ref IMethodReturnMessage message);
void Finally(ref IMethodReturnMessage message);
}

就简单看看一个基于当前组件框架的验证组件的实现:

//首先,我们需要定义一个接口来规范验证组件的行为

public interface IValidator
{
           //验证过程写在Perform中

           void Perform(IValidatedElement element);
}

 //比如说NotNull,也就是上文提到的判断属性值不为Null值得组件

public class NotNullAttribute:Attribute,IValidator

{

public void Perform(IValidatedElement element)
{
if(element.Value==null)
{

//可以throw 一个异常
OnFailed(element);
}
OnSucceed(element);
}

}

是不是很简单?再来一个非空字符判断组件(有没有感觉到这个判断过程散布在系统每个角落?)

public class NotWhiteSpaceAttribute:Attribute,IValidator

{

public void Perform(IValidatedElement element)
{
if(element.Value!=null)
{
string value = element.Value as string;
if(value!=null&&value.Trim().Length ==0)
{
OnFailed(element);
}
}
OnSucceed(element);
}

}

这时你也许要问这些组件是如何发挥作用的呢?这个就要提到ValidateInterceptor这个拦截器了!因为只有拦截住对这些加了Attribute的属性的操作过程,才能有效的织入我们的验证.

下面给出它的实现:

 

SqlCenter中的AOP实现public class ValidateInterceptor : IInterceptor
SqlCenter中的AOP实现


最后,回过头来看看,我们的NotNull验证组件是如何起作用的:

1.让我们的类继承于ContextBoundObject ,同时加上[AspectAttribute]

2.在我们需要不为null的属性上添加上[NotNull,NotWhiteSpaceAttribute]这个Attribute.

3.运行时:

   系统处理(get,set或方法实现上)遇到这个Attribute时,通过配置文件:

<interceptors>
<add key="ValidateInterceptor" value="SqlCenter.Validators.ValidateInterceptor, SqlCenter.Validators"/>
</interceptors>

发现处理者,并将这个消息加入到拦截器链中,再将任务转交给各自组件去处理(这里似乎也有Ioc思想和策略模式的运用) .

4.处理完成就返回,出现不符合约束要求的就做响应的处理.

上面是关于SqlCenter 中AOP思想的点点理解.

posted @ 2006-11-06 21:17 flyingchen 阅读(1220) 评论(7)  编辑 收藏 网摘 所属分类: 技术类Design Pattern架构研究Open SourceDotNet技术
SqlCenter中的AOP实现
  回复  引用  
#1楼 2006-11-06 22:16 | ant [未注册用户]
好文,收藏先!
  回复  引用  查看  
#2楼 2006-11-07 08:55 |      
对于必须继承自ContextBoundObject 一直比较感冒。
我现在也在做AOP,不过框架本身并不想暴露太多的AOP部分。
  回复  引用  查看  
#3楼 [楼主]2006-11-07 09:01 |      
@编写人生
对于单继承的C#来说,确实是个问题:(
  回复  引用  查看  
#4楼 2006-11-07 09:05 |      
继承ContextBoundObject来处理效率有点低。
即使不横切加入功能,对象创建或成员访问和普通对象差不是一个级别。
继承ContextBoundObject这种约束过于强制性,如果是接口还不错。
  回复  引用  查看  
#5楼 [楼主]2006-11-07 11:14 |      
@henry
对于从ContextBoundObject继承,确实是个比较头疼的问题.
至于效率上,不知道您是否能做点分析:),还有就是不怎么理解你的第2 句话,望指教!谢谢了!
  回复  引用  查看  
#6楼 2006-11-07 11:34 |      
@main
效率我是这样测的(第二个其实就是效率,打少了字:()
建立两个类有同样的方法一个是继承ContextBoundObject,一个没有。
然后测试两个类的实例化和方法调用的效率,具体测试情况忘(记得两者的效率差得挺大的);如果针对小范围应用还是可以接受,在大范围中使用就是考虑了。
有时为了保证业务具备横切的功能,有可能在基类继承ContextBoundObject;这有可能导致影响的范围比较大。
  回复  引用  查看  
#7楼 [楼主]2006-11-07 12:30 |      
@henry
感谢先,我已经看到你blog上这篇文章了:)

相关文章:

  • 2022-12-23
  • 2021-12-05
  • 2022-12-23
  • 2022-12-23
  • 2021-12-25
  • 2022-12-23
  • 2022-02-03
猜你喜欢
  • 2022-12-23
  • 2023-03-23
  • 2021-12-10
  • 2022-02-12
  • 2021-05-18
相关资源
相似解决方案