您的位置:首页 > 运维架构

使用PostSharp进行AOP框架设计:一个简单的原型

2007-09-13 20:28 1016 查看
AOP已经不是一个什么新名词了,在博客园使用关键字搜索可以查出n多条关于AOP的介绍,这里就不再赘述了。

Bruce Zhang's Blog里面有很多关于AOP介绍及其在.net下实现研究,总觉得如果什么都从头来写难免有自造轮子的嫌疑,但是目前也没有很成熟的AOP框架让我们能轻松完成基于AOP架构,不过一直以来都在关注的PostSharp开源项目日趋成熟,目前已发布了PostSharp 1.0 (Beta release 3)。即使如此,也还没能到应用到产品上的时候。

前段时间一直在封装一个权限系统,时常为如何给调用方提供一个良好的编程接口烦恼,加之前前段时间考虑的日志、异常接管、事务、缓存等等一些横向组件的架构分析,自然就想用AOP技术实现,但是由于实现难度实在不小作罢;这两天又重新学习研究了PostSharp的架构与实现思想,觉得还是尝试一下,将其融入现有框架;

早在年初就有不少前辈大师就如何使用这个东西撰写过文章,如Q.yuhenPostSharp - 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 Orders

{

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;

}

}

代码很简单,我是采用控制台应用实现的,如果您有兴趣,请下载Demo源码玩玩。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐