您的位置:首页 > 编程语言

轻便的AOP编程框架-PostSharp (参数获取)

2015-08-11 14:50 429 查看
http://www.cnblogs.com/techmango/archive/2011/05/23/postsharp_light_weight_aop_framwork.html

在学习 AOP的过程中认识了PostSharp这个AOP编程框架,觉得它很轻巧,使用起来也很方便,推荐大家使用.于是将它与其它AOP框架如 Spring.net中的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 override void OnEntry(MethodExecutionEventArgs eventArgs)

{

// 获取方法名称

Console.WriteLine("OnEntry:{0}.{1}", eventArgs.Method.ReflectedType, eventArgs.Method);

// 显示方法参数

ParameterInfo[] ps = eventArgs.Method.GetParameters();

object[] pv = eventArgs.GetArguments();

for (int i = 0; i < ps.Length; i++)

{

Console.WriteLine(" {0}={1}", ps[i].Name, pv[i]);

}

}

public override void OnExit(MethodExecutionEventArgs eventArgs)

{

Console.WriteLine("OnExit...");

}

}

public class MyClass

{

[AopMethod]

public int Test(int i)

{

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

return i++;

}

}

MyClass o = new MyClass();

o.Test(123);

输出:

OnEntry:MyClass.Int32 Test(Int32)

i=123

Test:123

OnExit...

整个过程非常简单:

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

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

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

4. 编译,执行。
PS:注意在编译时 VS STUDIO Output 窗口的输出内容,你会看到如下内容。其实 PostSharp 提供了一个 MSBuild Task,在我们每次编译时会调用它执行一些注入操作。
我们用反编译工具看 看注入后的方法内容。看完这些代码,大家应该能明白它是如何实现拦截的了吧。

static MyClass()

{

if (!~PostSharp~Laos~Implementation.initialized)

{

throw new LaosNotInitializedException();

}

~PostSharp~Laos~Implementation.~targetMethod~1 = methodof(MyClass.Test);

~PostSharp~Laos~Implementation.~aspect~1.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~1);

}

public int Test(int i)

{

int returnValue;

MethodExecutionEventArgs eventArgs;

try

{

object[] arguments = new object[] { i };

eventArgs = new MethodExecutionEventArgs(methodof(MyClass.Test, MyClass), this, arguments);

~PostSharp~Laos~Implementation.~aspect~1.OnEntry(eventArgs);

if (eventArgs.FlowBehavior == FlowBehavior.Return)

{

return (int) eventArgs.ReturnValue;

}

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

int num = i++;

returnValue = num;

eventArgs.ReturnValue = returnValue;

~PostSharp~Laos~Implementation.~aspect~1.OnSuccess(eventArgs);

returnValue = (int) eventArgs.ReturnValue;

}

catch (Exception exception)

{

eventArgs.Exception = exception;

~PostSharp~Laos~Implementation.~aspect~1.OnException(eventArgs);

switch (eventArgs.FlowBehavior)

{

case FlowBehavior.Continue:

return returnValue;

case FlowBehavior.Return:

return (int) eventArgs.ReturnValue;

}

throw;

}

finally

{

eventArgs.ReturnValue = returnValue;

~PostSharp~Laos~Implementation.~aspect~1.OnExit(eventArgs);

returnValue = (int) eventArgs.ReturnValue;

}

return returnValue;

}

我们可以使用通配符拦截更多的内容,以简化我们的编码。
>[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...");

}

}

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