标签:
最近貌似挺流行切面编程的,也不知道为什么,偶尔看到微信公众号里面有这样的主题,几个朋友也找我来讨论AOP的一些东西
抱着学习的态度,把PostSharp研究了下,记录一下个人认为比较重要的几个点
1,何为PostSharp
PostSharp采用特性的方式来对编译后的主业务流程方法逻辑横向静态注入截取数据,切入的中心为IL层。
盗用一张我觉得比较形象的图片来解释一下AOP的工作原理,
第一种是运行时编译:
第二种是编译时已经确定AOP如何介入
2,如何安装PostSharp
搜一下PostSharp的官网,然后下载,网上很多人说要收费,不过我选择的是个人开发者,貌似也没找我要钱啊。
安装完了就可以在Visual Studio中出现,引用即可。
3,具体代码示例
首先定义一个LogAttribute:
/// <summary> /// 目前记录了方法的执行时间,输出样例: /// [2016-04-12 10:39:36]方法 GetUser 执行结束,用时 164ms /// </summary> [Serializable] public class LogsAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect { [NonSerialized] private Stopwatch _stopwatch; public object CreateInstance(AdviceArgs adviceArgs) { return MemberwiseClone(); } public override void OnEntry(MethodExecutionArgs eventArgs) { _stopwatch.Restart(); Arguments arguments = eventArgs.Arguments; StringBuilder sb = new StringBuilder(); ParameterInfo[] parameters = eventArgs.Method.GetParameters(); for (int i = 0; arguments != null && i < arguments.Count; i++) { //进入的参数的值 sb.Append(parameters[i].Name + "=" + arguments[i] + ""); } LoggerHelper.Writelog("方法 " + eventArgs.Method.Name + " 开始执行,参数为:" + sb); } public override void OnSuccess(MethodExecutionArgs args) { _stopwatch.Stop(); LoggerHelper.Writelog( "方法 " + args.Method.Name + " 执行结束,用时 " + _stopwatch.ElapsedMilliseconds + "ms", LogLevel.Success ); } public override void OnException(MethodExecutionArgs args) { _stopwatch.Stop(); LoggerHelper.Writelog( "方法 " + args.Method.Name + " 执行出错,错误为:" + args.Exception, LogLevel.Error ); } /// <summary> /// 初始化类必须的方法 /// </summary> public void RuntimeInitializeInstance() { _stopwatch = new Stopwatch(); } }
有以下几点是必须要注意的
OnMethodBoundaryAspect是代表这个Attribute是用于方法的,不适用于其他,比如说属性或者字段可以使用LocationLevelAspect
OnEntry,OnSuccess之类的重载方法执行顺序如下,还是比较形象的(这段代码是抄来的)
int MethodA(object arg0, int arg1) { //函数进入时添加OnEntry()方法 OnEntry(); try { // 函数在此运行完毕 //如果成功则继续运行OnSuccess()方法 OnSuccess(); return returnValue; } catch (Exception e) { //如果函数执行有问题,则运行OnException()方法 OnException(); } finally { //最后执行OnExit()方法 OnExit(); } }
IInstanceScopedAspect 接口允许当前Attribute拥有与宿主同样的LifeCycle,拿上面的代码来说,StopWatch要想使用必须实例化,通过IInstanceScopedAspect里面的RuntimeInitializeInstance()方法允许其实例化。
4,如何使用当前的Attribute
我们刚刚写了个LogAttribute,同时定义它适用于方法
[Logs] public Customer GetUser(string userName) { Customer user = null; //omit return user; }
输出的结果如下:
[2016-04-12 09:20:19]方法 GetUser 开始执行,参数为:userName=xxxxx [2016-04-12 09:20:19]方法 GetUser 执行结束,用时 25ms
5,作为一个用惯MSDN的人来说,文档是最好的朋友:http://doc.postsharp.net/conceptual-documentation
标签:
原文地址:http://www.cnblogs.com/fffbmdmw/p/5384660.html