您的位置:首页 > 其它

PostSharp - 面向方面系统(转)

2008-08-15 10:16 155 查看
PostSharp 是一个令人兴奋的项目,他结合了 MSBuild Task 和 MSIL Injection 技术,从另外一个角度实现 AOP 编程。试用过后你会感觉到其便利性,我们和以往基于 Dynamic Proxy 方式的 AOP 解决方案做个比较。

由于采用 MSIL Injection,因此静态代码注入的执行效率要高于使用 Reflection Emit。

使用 MSBuild Task,使得开发人员可以像使用编译器内置 Attribute 那样使用 AOP。

可以拦截任意方法,而 Dynamic Proxy 方式的 AOP 往往采取继承方式来拦截 Virtual 方法。

拥有更多的控制权。包括中断执行流程,修改参数和返回值等等。

还可以拦截 Field Access、Exception 等操作。

无需将对象创建代码改成 "new proxy()",更加透明。

可以使用通配符进行多重拦截匹配。

静态注入带来的问题更多的是注入代码的质量和调试复杂度。

我们写一个简单的例子,看看效果。

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;

using PostSharp.Laos;

[Serializable]

public class AopMethodAttribute : OnMethodBoundaryAspect

public class MyClass

MyClass o = new MyClass();

o.Test(123);

输出:

OnEntry:MyClass.Int32 Test(Int32)

i=123

Test:123

OnExit...

整个过程非常简单:

1. 创建一个继承自 OnMethodBoundaryAspect 的特性类,用于拦截方法。

2. override 特定的方法,执行拦截操作。方法参数提供了各种操作能力。

3. 向目标方法添加特性。

4. 编译,执行。

或许你会好奇,AopMethodAttribute 是如何被创建实例,并被执行的呢?

1. 注意编译时 VS2005 Output 窗口的输出内容,你会看到如下内容。其实 PostSharp 提供了一个 MSBuild Task,在我们每次编译时会调用它执行一些注入操作。

PostSharp 1.0 [1.0.4.162] - Copyright (c) Gael Fraiteur and Community, 2006.

2. 用反编译工具看看注入后的方法内容。看完这些代码,就算我不说,你也能明白它是如何实现拦截的了。

static MyClass()

public int Test(int i)

我们可以使用通配符拦截更多的内容,以简化我们的编码。

[AopMethod(AttributeTargetMembers="T*")]

public class MyClass

{

public int T1(int i)

{

Console.WriteLine("T1:{0}", i);

return i++;

}

public void T2(string s)

{

Console.WriteLine("T2:{0}", s);

}

}

我们继续写一点其它的例子,诸如拦截属性访问和异常。

Field Aspect

[Serializable]

public class AopPropertyAttribute : OnFieldAccessAspect

{

public override void OnGetValue(FieldAccessEventArgs eventArgs)

{

Console.WriteLine("ExposedFieldValue:{0}; StoredFieldValue:{1}",

eventArgs.ExposedFieldValue, eventArgs.StoredFieldValue);

}

public override void OnSetValue(FieldAccessEventArgs eventArgs)

{

Console.WriteLine("ExposedFieldValue:{0}; StoredFieldValue:{1}",

eventArgs.ExposedFieldValue, eventArgs.StoredFieldValue);

}

}

public class MyClass

{

[AopProperty]

private int x;

public int X

{

get { return x; }

set { x = value; }

}

}

Exception Aspect

[Serializable]

public class AopExceptionAttribute : OnExceptionAspect

{

public override void OnException(MethodExecutionEventArgs eventArgs)

{

Console.WriteLine(eventArgs.Exception.Message);

eventArgs.FlowBehavior = FlowBehavior.Return;

}

}

public class MyClass

{

[AopException]

public void Test(int i)

{

throw new Exception("Error");

}

}
更详细的信息,请访问 PostSharp 网站,或者查阅其帮助文件。

结论:

1.方法执行的日志记录可以用AOP实现

2.表之间的级联删除可以用AOP实现

3.数据库操作日志可以用AOP记录(因为数据库提供商不提供它的日志,导致第三方数据库同步无法便利实现)

...
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: