基于PostSharp的AOP框架设计 .
上一篇 / 下一篇 2012-09-12 09:20:13 / 个人分类:阅读整理
- AOP已经不是一个什么新名词了,在博客园使用关键字搜索可以查出n多条关于AOP的介绍,这里就不再赘述了。
- 在Bruce Zhang's Blog里面有很多关于AOP介绍及其在.net下实现研究,总觉得如果什么都从头来写难免有自造轮子的嫌疑,但是目前也没有很成熟的AOP框架让我们能轻松完成基于AOP架构,不过一直以来都在关注的PostSharp开源项目日趋成熟,目前已发布了PostSharp 1.0 (Beta release 3)。即使如此,也还没能到应用到产品上的时候。
- 前段时间一直在封装一个权限系统,时常为如何给调用方提供一个良好的编程接口烦恼,加之前前段时间考虑的日志、异常接管、事务、缓存等等一些横向组件的架构分析,自然就想用AOP技术实现,但是由于实现难度实在不小作罢;这两天又重新学习研究了PostSharp的架构与实现思想,觉得还是尝试一下,将其融入现有框架;
- 早在年初就有不少前辈大师就如何使用这个东西撰写过文章,如Q.yuhen的PostSharp - Lightweight Aspect-Oriented System该仁兄下面见解很到位:
- 和以往基于 Dynamic Proxy 方式与 AOP 解决方案做个比较。
- 由于采用 MSIL Injection,因此静态代码注入的执行效率要高于使用 Reflection Emit。
- 使用 MSBuild Task,使得开发人员可以像使用编译器内置 Attribute 那样使用 AOP。
- 可以拦截任意方法,而 Dynamic Proxy 方式的 AOP 往往采取继承方式来拦截 Virtual 方法。
- 拥有更多的控制权。包括中断执行流程,修改参数和返回值等等。
- 还可以拦截 Field Access、Exception 等操作。
- 无需将对象创建代码改成 "new proxy()",更加透明。
- 可以使用通配符进行多重拦截匹配。
- 静态注入带来的问题更多的是注入代码的质量和调试复杂度。
- 另外有一老外的Using AOP and PostSharp to Enhance Your CodeAB两部分,相当精彩,本文就是在参考这两篇好文的基础上做的。
- 我们假设有这么个场景,其实这也是实际业务中很常见的处理方式:有一定单管理模块,具备新增、删除两功能,我们在新增删除的时候必须校验权限,在删除的时候还必须记录日志,出现异常了还必须捕捉并记录异常;
- 按以前的写法我们可能很麻烦,我们要如此这般的写:
- public class XOrders
- {
- public bool Add(string id, string orderName)
- {
- try
- {
- if (User.AddEnable)
- {
- //TODO:新增订单的实现
- Console.WriteLine("正在执行新增订单方法的操作,回车继续……");
- Console.ReadLine();
- Console.WriteLine("您添加订单成功:编号:{0},名称:{1}", id, orderName);
- return true;
- }
- else
- {
- //
- }
- }
- catch (Exception)
- {
- //TODO:记录异常的实现
- throw;
- }
- return true;
- }
- public bool Delete(string id)
- {
- try
- {
- if (User.DeleteEnable)
- {
- //TODO:删除订单的实现
- Console.WriteLine("您删除订单成功:编号:{0}", id);
- }
- else
- {
- //
- }
- }
- catch (Exception)
- {
- //TODO:记录异常的实现
- throw;
- }
- return true;
- }
- 这种写的弊端我就不多说了,有很多先驱都阐述过……
- 我要演示的是采用AOP技术的框架原型实现:
- 首先我们应该安装PostSharp(一定要安装要不能没办法注入处理代码)
- 然后我们实现Orders对象
- using System;
- namespace PostSharp.Demo
- {
- public class Orders
- {
- [Permission]
- [Exception]
- public bool Add(string id, string orderName)
- {
- Console.WriteLine("正在执行新增订单方法的操作,回车继续……");
- Console.ReadLine();
- Console.WriteLine("您添加订单成功:编号:{0},名称:{1}", id, orderName);
- return true;
- }
- [Logger]
- [Permission]
- [Exception]
- public bool Delete(string id)
- {
- Console.WriteLine("您删除订单成功:编号:{0}", id);
- return true;
- }
- }
- }
- 当然还要模拟一个用户资格认证
- namespace PostSharp.Demo
- {
- /// <summary>
- /// 静态的用户对象,用于存放当前登录用户,成员资格
- /// </summary>
- public static class User
- {
- private static string _userId;
- public static string UserId
- {
- get { return _userId; }
- set { _userId = value; }
- }
- public static bool AddEnable
- {
- get
- {
- return (_userId.ToLower() == "admin");
- }
- }
- public static bool DeleteEnable
- {
- get
- {
- return (_userId.ToLower() == "admin");
- }
- }
- }
- }
- 再然后我们实现权限控制方面PermissionAttribute,日志方面LoggerAttribute,异常处理方面ExceptionAttribute……
- PermissionAttribute
- using System;
- using PostSharp.Laos;
- namespace PostSharp.Demo
- {
- [Serializable]
- [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
- public class PermissionAttribute : OnMethodBoundaryAspect
- {
- public override void OnEntry(MethodExecutionEventArgs eventArgs)
- {
- if (!User.AddEnable)
- {
- Console.WriteLine("用户:【{0}】没有权限:【{1}】", User.UserId, eventArgs.Method);
- eventArgs.FlowBehavior = FlowBehavior.Return;
- }
- }
- }
- }
- LoggerAttribute
- using System;
- using PostSharp.Laos;
- namespace PostSharp.Demo
- {
- [Serializable]
- [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
- public sealed class LoggerAttribute : OnMethodInvocationAspect
- {
- public override void OnInvocation(MethodInvocationEventArgs eventArgs)
- {
- DateTime time = DateTime.Now;
- string log = "时间:{0},操作人员:{1},操作:{2}!";
- object[] arg = eventArgs.GetArguments();
- log = String.Format(log, time, User.UserId, "删除Id为" + arg[0].ToString() + "的订单!");
- System.IO.File.WriteAllText("C://Log.Txt", log);
- }
- }
- }
- ExceptionAttribute
- using System;
- using PostSharp.Laos;
- namespace PostSharp.Demo
- {
- [Serializable]
- [global::System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)]
- public class ExceptionAttribute : OnExceptionAspect
- {
- public override void OnException(MethodExecutionEventArgs eventArgs)
- {
- Console.WriteLine("程序出现异常:{0}", eventArgs.Exception.Message);
- eventArgs.FlowBehavior = FlowBehavior.Return;
- }
- }
- }
- 然后再用控制台程序测试下能不能成功
- Orders order = new Orders();
- Console.WriteLine("请输入用户名:");
- User.UserId = Console.ReadLine();
- Console.WriteLine("请输入密码:");
- Console.ReadLine();
- string id;
- LRedo:
- Console.WriteLine("请输入您要执行的操作:新增(A),删除(D),退出(X)");
- string opt = Console.ReadLine();
- if (opt.ToLower() == "a")
- {
- Console.WriteLine("请输入订单编号:");
- id = Console.ReadLine();
- Console.WriteLine("请输入订单名称:");
- string name = Console.ReadLine();
- order.Add(id, name);
- }
- else if (opt.ToLower() == "d")
- {
- Console.WriteLine("请输入订单编号:");
- id = Console.ReadLine();
- order.Delete(id);
- }
- else if (opt.ToLower() == "x")
- {
- }
- else
- {
- Console.WriteLine("您的输入不正确,请重新输入!");
- goto LRedo;
- }
- Console.WriteLine("按任意键退出……");
- Console.ReadLine();
- 写完这些我们再反编译一下生成的exe文件,发现里面的Orders成了这模样了,神奇了?
- public class Orders
- {
- // Methods
- static Orders()
- {
- if (!~PostSharp~Laos~Implementation.initialized)
- {
- LaosNotInitializedException.Throw();
- }
- ~PostSharp~Laos~Implementation.~targetMethod~1 = methodof(Orders.Add);
- ~PostSharp~Laos~Implementation.~aspect~1.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~1);
- ~PostSharp~Laos~Implementation.~targetMethod~5 = methodof(Orders.Delete);
- ~PostSharp~Laos~Implementation.~aspect~5.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~5);
- ~PostSharp~Laos~Implementation.~targetMethod~4 = methodof(Orders.Delete);
- ~PostSharp~Laos~Implementation.~aspect~4.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~4);
- ~PostSharp~Laos~Implementation.~targetMethod~3 = methodof(Orders.Add);
- ~PostSharp~Laos~Implementation.~aspect~3.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~3);
- ~PostSharp~Laos~Implementation.~targetMethod~2 = methodof(Orders.Delete);
- ~PostSharp~Laos~Implementation.~aspect~2.RuntimeInitialize(~PostSharp~Laos~Implementation.~targetMethod~2);
- }
- private bool ~Delete(string id)
- {
- Console.WriteLine("您删除订单成功:编号:{0}", id);
- return true;
- }
- public bool Add(string id, string orderName)
- {
- bool ~returnValue~1;
- MethodExecutionEventArgs ~laosEventArgs~7;
- try
- {
- object[] ~arguments~6 = new object[] { id, orderName };
- ~laosEventArgs~7 = new MethodExecutionEventArgs(methodof(Orders.Add, Orders), this, ~arguments~6);
- ~PostSharp~Laos~Implementation.~aspect~1.OnEntry(~laosEventArgs~7);
- if (~laosEventArgs~7.FlowBehavior == FlowBehavior.Return)
- {
- return (bool) ~laosEventArgs~7.ReturnValue;
- }
- try
- {
- Console.WriteLine("正在执行新增订单方法的操作,回车继续……");
- Console.ReadLine();
- Console.WriteLine("您添加订单成功:编号:{0},名称:{1}", id, orderName);
- ~returnValue~1 = true;
- }
- catch (Exception ~exception~2)
- {
- object[] ~arguments~3 = new object[] { id, orderName };
- MethodExecutionEventArgs ~laosEventArgs~4 = new MethodExecutionEventArgs(methodof(Orders.Add, Orders), this, ~arguments~3);
- ~laosEventArgs~4.Exception = ~exception~2;
- ~PostSharp~Laos~Implementation.~aspect~3.OnException(~laosEventArgs~4);
- switch (~laosEventArgs~4.FlowBehavior)
- {
- case FlowBehavior.Continue:
- goto Label_0145;
- case FlowBehavior.Return:
- ~returnValue~1 = (bool) ~laosEventArgs~4.ReturnValue;
- goto Label_0145;
- }
- throw;
- }
- Label_0145:
- ~laosEventArgs~7.ReturnValue = ~returnValue~1;
- ~PostSharp~Laos~Implementation.~aspect~1.OnSuccess(~laosEventArgs~7);
- ~returnValue~1 = (bool) ~laosEventArgs~7.ReturnValue;
- }
- catch (Exception ~exception~5)
- {
- ~laosEventArgs~7.Exception = ~exception~5;
- ~PostSharp~Laos~Implementation.~aspect~1.OnException(~laosEventArgs~7);
- switch (~laosEventArgs~7.FlowBehavior)
- {
- case FlowBehavior.Continue:
- return ~returnValue~1;
- case FlowBehavior.Return:
- return (bool) ~laosEventArgs~7.ReturnValue;
- }
- throw;
- }
- finally
- {
- ~laosEventArgs~7.ReturnValue = ~returnValue~1;
- ~PostSharp~Laos~Implementation.~aspect~1.OnExit(~laosEventArgs~7);
- ~returnValue~1 = (bool) ~laosEventArgs~7.ReturnValue;
- }
- return ~returnValue~1;
- }
- [DebuggerNonUserCode]
- public bool Delete(string id)
- {
- bool ~returnValue~2;
- MethodExecutionEventArgs ~laosEventArgs~8;
- try
- {
- object[] ~arguments~7 = new object[] { id };
- ~laosEventArgs~8 = new MethodExecutionEventArgs(methodof(Orders.Delete, Orders), this, ~arguments~7);
- ~PostSharp~Laos~Implementation.~aspect~2.OnEntry(~laosEventArgs~8);
- if (~laosEventArgs~8.FlowBehavior == FlowBehavior.Return)
- {
- return (bool) ~laosEventArgs~8.ReturnValue;
- }
- try
- {
- Delegate delegateInstance = new ~PostSharp~Laos~Implementation.~delegate~0(this.~Delete);
- object[] arguments = new object[] { id };
- MethodInvocationEventArgs eventArgs = new MethodInvocationEventArgs(delegateInstance, arguments);
- ~PostSharp~Laos~Implementation.~aspect~5.OnInvocation(eventArgs);
- ~returnValue~2 = (bool) eventArgs.ReturnValue;
- }
- catch (Exception ~exception~3)
- {
- object[] ~arguments~4 = new object[] { id };
- MethodExecutionEventArgs ~laosEventArgs~5 = new MethodExecutionEventArgs(methodof(Orders.Delete, Orders), this, ~arguments~4);
- ~laosEventArgs~5.Exception = ~exception~3;
- ~PostSharp~Laos~Implementation.~aspect~4.OnException(~laosEventArgs~5);
- switch (~laosEventArgs~5.FlowBehavior)
- {
- case FlowBehavior.Continue:
- goto Label_0160;
- case FlowBehavior.Return:
- ~returnValue~2 = (bool) ~laosEventArgs~5.ReturnValue;
- goto Label_0160;
- }
- throw;
- }
- Label_0160:
- ~laosEventArgs~8.ReturnValue = ~returnValue~2;
- ~PostSharp~Laos~Implementation.~aspect~2.OnSuccess(~laosEventArgs~8);
- ~returnValue~2 = (bool) ~laosEventArgs~8.ReturnValue;
- }
- catch (Exception ~exception~6)
- {
- ~laosEventArgs~8.Exception = ~exception~6;
- ~PostSharp~Laos~Implementation.~aspect~2.OnException(~laosEventArgs~8);
- switch (~laosEventArgs~8.FlowBehavior)
- {
- case FlowBehavior.Continue:
- return ~returnValue~2;
- case FlowBehavior.Return:
- return (bool) ~laosEventArgs~8.ReturnValue;
- }
- throw;
- }
- finally
- {
- ~laosEventArgs~8.ReturnValue = ~returnValue~2;
- ~PostSharp~Laos~Implementation.~aspect~2.OnExit(~laosEventArgs~8);
- ~returnValue~2 = (bool) ~laosEventArgs~8.ReturnValue;
- }
- return ~returnValue~2;
- }
- }
TAG:
标题搜索
日历
|
|||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
1 | 2 | 3 | 4 | ||||||
5 | 6 | 7 | 8 | 9 | 10 | 11 | |||
12 | 13 | 14 | 15 | 16 | 17 | 18 | |||
19 | 20 | 21 | 22 | 23 | 24 | 25 | |||
26 | 27 | 28 | 29 | 30 | 31 |
我的存档
数据统计
- 访问量: 11616
- 日志数: 25
- 建立时间: 2007-07-25
- 更新时间: 2015-03-26