轻便的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
在学习 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
相关文章推荐
- 【Java解析XML】【二】JDK中的XML解析操作
- java io操作文件
- Coding 代码管理快速入门
- 【Java解析XML】【三】JDOM介绍
- [自学AndroidStudio系列]新的开始:安装和导入原Eclipse项目
- 编写高质量的代码——从命名入手
- PHP文件包含语句
- spring注解之@service等
- Struts2+Spring4+Hibernate4环境搭建
- Java中的栈Stack
- 算法题(JAVA实现)——网易校招2015
- 黑马程序员——C语言笔记之数据类型与常量
- myeclipse安装svn插件的多种方式
- C++中的抽象数据类型
- C++类的构造函数 后单冒号加基类 例如:CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
- PHP之Traits
- qt dbus 的一入门文章
- Yii中CDbCriteria查询条件收集
- QwtPlot画曲线
- android学习笔记之使用Eclipse搭建web服务器实现Android客户端登录