关于面向方面编程的帮助和信息

问题描述:

我是面向方面编程思想的新人,但我想探讨在我的项目中使用它以处理日志记录,报告等的想法。为此,我有一些问题:关于面向方面编程的帮助和信息

  • 我是否应该为这些有限的目的而探索AOP的这条路径?
  • 什么.NET框架支持AOP可用?
  • 哪这些框架的支持流畅的界面(我讨厌XML配置):)
+0

什么是流利的接口(API?)与XML配置有关吗? – 2009-02-18 02:52:12

+0

流利的界面可以替代xml配置。看流利-Nhibernate与nhiberate。具有流畅的界面意味着它可以被重构。 – 2009-02-18 11:02:42

面向方面编程不仅仅是记录,报告等等,你会看到如果你看看PostSharp的网站。就我个人而言,我没有做过那么多的静态IL编织,主要是动态IL生成来创建AOP拦截器,当我这样做时,我主要使用它来包装和拦截控制容器反转的解析。

AOP可以改善异常处理,改善跟踪,改善交易拦截。

NHibernate例如有一种AOP,即使它在编译时是简单的事件处理程序是静态的;但对于引擎中的某些事件,您可以附加拦截器(又名方面,事件是切入点等) - 我使用它来将IoC业务实体注入到我的域对象中。

强大的AOP的框架让你概括和更强大让你概括W/O开销在运行;原则上你有几种不同的做法

(0)。 (不是真的) “预处理器”,在C++ AOP又名模板的ifdef等

  1. 反射 “AOP”
  2. IL-代在通过Reflection.Emit的运行时,需要高的信任。这是Castle项目中的DynamicProxy2路径。 DynamicProxy2非常好,大量的工作已经进入!此外,afaik PatternsAndPractices策略框架也使用这种方法,并使用大量的XML,尽管它们有自己的生成器。 NHibernate依赖于DynProx2。
  3. 要在运行时IL编译+ Assembly.Load(...)通过使用System.CodeDom.Compiler,然后加载您创建assmblies,需要高度信任。也可以使用Boo.Compiler等其他编译器进行编译,因为它会创建“全局函数程序集”,您可以使用“脚本化”方式调用该函数,但现在我们稍微移出AOP。
  4. 探查的API(不要问我关于他们)
  5. 依托运行时框架:扩展MarshalByRef/ContextBoundObject see link并使用.NET中的远程基础设施做AOP,这是相当复杂的,引进的依赖你可能不想。
  6. 后编译静态IL编织,PostSharp和Mono.Cecil有一个等价的Reflection.Emit,但这个没有虚拟方法调用具体子类的错误(如果我没记错的话)像Reflection.Emit和会很高兴地检查您的代码,类似于Assembly.ReflectionOnlyLoad,并且还允许您将IL操作输出到该代码中。如果您正在寻找一种相当低级的方法,这是一个很好的选择;并不需要那么高的信任度。
  7. 通过p/invoke在托管代码中为非托管回调添加扩展点到C/C++,但这需要一些思考,因为例外不​​会很快地跨越m/um内存边界(相反,它会使应用程序混乱) ,除非您在Windows中使用托管的异常框架使用VC++/C#,否则这可能会导致严重错误。您可以将回调传递给C,并从C#将p/invoke传入C,并且可能会将回调从C传递给C#,以及您在C#中定义委托的时间。扩展点可能必须通过静态或动态IL-weaver +切点来完成。

用法在交易 看一看Castle.Facilities.AutomaticTransactionManagement.TransactionFacility为处理使用AOP交易的好方法和DynamicProxy2的拦截能力。与System.Transcations和System.EnterpriseServices集成的事务工具是您正在使用分布式事务协调器(COM组件)来管理事务。此外,还有多个p/invoke进入内核的示例,用于处理允许您在NTFS和注册表上使用事务的TxF and TxR components of the Vista-kernel (aka Server 2008),从而确保您执行CRUD的操作是ACID,该操作也很好地与System.Transactions集成创建嵌套事务。

用于不变验证的用法 您也可以将它们用于合同设计,方法是在参数中附加一些属性。

public void PerformOperation([NotNull, NotEmpty] string value) { 
// use string 
[NotNull] return new string(' ', 5); // can return with attributes as well 
} 

此时的问题是附加此元数据并在运行时检查它的开销。但是,您可以指定仅在用DEBUG编译时应用约束检查方面,然后才能指定此元数据 - 不会导致性能大幅下降。

如果您正在寻找公理证据,请查看Sing#/ Spec#,因为这更正式,而且工作由编译器完成。

事情要注意的 最重要的一点要注意的是,如果一个问题,即一些片之前或你的方法是改变控制流后运行的代码,可能返回意外的类型,返回得太早或者一般情况下不会表现出您所调用的方法的意图,您可能会遇到难以调试的错误。另外,要小心从属性抛出异常,因为你永远不知道什么时候或从什么程序集开始反射,当你期望的时候,你的属性的反思可能不会发生。当我在属性中附加类型并仔细检查它们时,这发生在我自己身上。

还要提防你打开一个可能的攻击媒介,添加全局“切点”,如果有人可以访问,可以用来重定向系统的大部分。

其他框架 如果您有兴趣了解更多有关AOP一般我建议你检查出Qi4J里卡德奥伯格的介绍,它是一个Java AOP的一个非常好的框架(Java有稍微不同的继承对象的语义虽然这使得一个凌晨一点小技巧就在C#使用/ F#/ Nermle /啵不管。

AOP +加载项 使用具有运行时生成的组件面向方面的编程的另一个有趣的可能性如那些dynamicproxy2创建,是你也可以使用它们来包装跨越应用程序边界的对象reby简化了添加管道的创建。我暗中希望微软在为3.5创建AddIn-framework时使用它,但是他们选择了静态代码生成方式,这给开发人员创建插件带来了相当大的开销。问题是,一个加载“多于反射”到AppDomain中的类型不能再次卸载,除非完整的AppDomain被卸载,所以你需要1)反思插件而不加载它来查看它的能力,除非你允许写入或生成大量的手动元数据(并相信这一点),2)某些对象持有对象的句柄,以便它不被GCC处理,并且你不知道类型(因此IContract程序集和AddInHandle类) - 这可能可以通过动态代理/ AOP以很好的方式完成。

在全局垃圾收集中使用AOP ...在公共语言基础结构上运行在linux/windows上的分布式系统中。这篇文章有点难以下载,所以我知道它在哪里。

邮政Scriptum (如果您正在使用CLR的非标准语言,而不是DLR IL-编织可能会产生不符合标准的代码。对于F#特别有趣,我认为,这是因为使用一个很多的非标准代码语言的很大好处(元组说) - 你可以用[程序集:CLSCompliant]标记你的程序集,如果你想得到这个编译时警告。)

AOP有趣的是,我也是如此。在我看来,日志和性能监控,报告是AOP旨在处理的内容。对于.NET,Post Sharp是一个非常好的AOP框架。

我只尝试了一下,但它似乎很好的实施。

不要以为它的东西完全不同。 AOP通过减少耦合,增加内聚力,通过给予某种类型1单一责任的目标来分担顾虑,从而改进(IMO)您的设计。如果您来自.net世界PostSharp使用自定义属性来编织建议。如果您来自Java世界,则可以使用名为AspectJ的Java扩展。 AOP拥有比您通常看到的更多的应用程序。

如果您要查看Post Sharp,可以从CodePlex下载Google Book Downloader。我认为这个项目使用它。

我不能说具体的.NET,但AOP和能够挂钩到任意方法的更一般的想法,是一种方便的技术,可以解决一些其他毛病。

一个例子是design by contract。假设您有大量方法可用于您想要应用某些通用合同。您可以在调用每个方法前后添加一些“建议”(AOP术语),而不必削减&将其粘贴到每种方法中。

在测试过程中,了解某些内部方法发生的情况通常很有用。它被调用了多少次,也许它返回了什么。您可以添加一个方面来执行该监控,而无需将干扰测试代码添加到方法本身。编辑该方法的代码可能甚至不可能。

只要注意方面如何实施。有些实现是复杂的预处理器,可能会使您的代码更加复杂。其他人能够顺利地融入语言。动态语言很好地处理AOP。 Perl具有Aspect.pm用于AOP,更普通的Hook::LexWrap用于完成方法钩子。