有关面向方面编程的帮助和信息 [英] Help and Information about Aspect Oriented Programming

查看:26
本文介绍了有关面向方面编程的帮助和信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是面向方面编程思想的新手,但我想探索在我的项目中使用它来处理日志记录、报告等的想法.为此,我有一些问题:

I'm a newcomer to the idea of aspect-oriented programming but I would like to explore the idea of using it on my project for handling logging, reporting, etc. To this end I have some questions:

  • 为了这些有限的目的,我是否应该费心探索这条 AOP 之路?
  • 有哪些支持 AOP 的 .NET Framework 可用?
  • 哪些框架支持流畅的界面(我讨厌 XML 配置):)

推荐答案

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

Aspect Oriented Programming is so much more than just logging, reporting et cetera, as you will see if you have a look at PostSharp's web site. Personally I haven't done so much static IL weaving, mostly dynamic IL generation to create AOP interceptors and when doing so I have mostly been using it to wrap and intercept resolves from inversion of control containers.

AOP 可以改进异常处理,改进跟踪,改进事务拦截.

AOP can improve exception handling, improve tracing, improve transaction interception.

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

NHibernate for example has a sort of AOP, even though it's static at compile-time in terms of simple event handlers; but for certain events in the engine you can attach interceptors (aka aspects, the events being the point-cuts etc) -- I use this to inject, using IoC business entities into my domain objects.

强大的 AOP 框架允许您进行泛化,更强大的允许您在运行时没有开销的情况下进行泛化;原则上,您有几种不同的方法:

Powerful AOP-frameworks allow you to generalize and even more powerful allow you to generalize w/o overhead at runtime; in principle you have a few different ways of doing it:

(0).(不是真的)C++、ifdefs 等中的预处理器"AOP 又名模板

(0). (not really) "pre-processor" AOP aka templates in C++, ifdefs etc

  1. 反射AOP"
  2. 在运行时通过 Reflection.Emit 生成 IL,需要高度信任.这是 Castle 项目中 DynamicProxy2 所采用的路径.DynamicProxy2 相当不错,而且已经做了很多工作!此外,afaik PatternsAndPractices Policy Framework 也使用这种方法,有很多 XML,尽管有自己的生成器.NHibernate 依赖于 DynProx2.
  3. 在运行时通过使用 System.CodeDom.Compiler 进行 IL 编译 + Assembly.Load(...),然后加载您创建的程序集,需要高度信任.也可以使用任何其他编译器(如 Boo.Compiler)进行编译,因为它会创建全局函数程序集",您可以以脚本化"方式调用它,但现在我们正在稍微远离 AOP.
  4. Profiler API(不要问我这些)
  5. 依赖运行时框架:扩展MarshalByRef/ContextBoundObject 见链接 并使用 .Net 中的远程处理基础设施来执行 AOP,这非常复杂,并且会引入您可能不想要的依赖项.
  6. Post-compile static IL-weaving、PostSharp 和 Mono.Cecil 具有等效的 Reflection.Emit,但是这个没有像 Reflection.Emit 和将很乐意检查类似于 Assembly.ReflectionOnlyLoad 的代码,并且还允许您将 IL 操作输出到该代码中.如果您正在寻找一种相当低级的方法,这是一个不错的选择;不需要那么高的信任度.
  7. 在您的托管代码中添加扩展点以通过 p/invoke 向 C/C++ 的非托管回调添加扩展点,但这需要一些思考,因为异常不会愉快地跨越 m/um 内存边界(相反,它会使您的应用程序混乱),除非您在 Windows 中使用 VC++/C# 和托管异常框架,否则这可能会导致严重的段错误.您可以将回调传递给 C 并从 C# 调用/调用到 C,并且可能将回调从 C 传递到 C#,只要您在 C# 中定义委托.扩展点可能必须通过静态或动态 IL-weaver + 切入点来完成.
  1. Reflection "AOP"
  2. IL-generation at runtime through Reflection.Emit, requires high trust. This is the path DynamicProxy2 in the Castle project has taken. DynamicProxy2 is rather nice and lots of work has gone into it! Also, afaik PatternsAndPractices Policy Framework uses this approach as well, with lots of XML, although with their own generator. NHibernate has a dependency on DynProx2.
  3. To IL-compilation + Assembly.Load(...) at runtime through using System.CodeDom.Compiler, then loading your created assmblies, requires high trust. Compiling with any other compiler like Boo.Compiler is also possible as it creates "global function assemblies" which you can call in a 'scripted' way, but now we're moving out of AOP a bit.
  4. Profiler APIs (don't ask me about them)
  5. Relying on the runtime framework: extending MarshalByRef/ContextBoundObject see link and using the remoting-infrastructure in .Net to do AOP, which is quite complex and introduce dependencies you might not want.
  6. Post-compile static IL-weaving, PostSharp and Mono.Cecil has an equivalent of Reflection.Emit, but this one doesn't have bugs for virtual methods calls in concrete subclasses (if I remember correctly) like Reflection.Emit and will gladly inspect your code similar to Assembly.ReflectionOnlyLoad and will also allow you to output IL-operations into that code. This is a good candidate if you are looking for a rather low-level approach; doesn't require as high trust.
  7. Adding extension points in your managed code for unmanaged callbacks to C/C++ through p/invoke, but this requires some thought as exceptions don't cross m/um memory-boundaries happily (rather, it will mess your application up), and unless you're using VC++/C# in Windows with managed exception framework this could seg-fault quite badly. You can pass callback to C and p/invoke into C from C# and probably pass callbacks from C to C# as well as long as you define the delegate in C#. The extension points would probably have to be done through a static or dynamic IL-weaver + point-cuts.

交易中的使用查看 Castle.Facilities.AutomaticTransactionManagement.TransactionFacility使用 AOP 处理事务的好方法和 DynamicProxy2 的拦截能力.与 System.Transcations 和 System.EnterpriseServices 集成的事务工具是您使用分布式事务协调器(COM 组件)来管理事务.此外,还有多个 p/invoke 进入内核的示例来处理 Vista 内核(又名 Server 2008)的 TxF 和 TxR 组件,允许您在 NTFS 和注册表上使用事务,从而确保 CRUDdo 是 ACID,它也很好地与 System.Transactions 集成以创建嵌套事务.

Usages in transactions Have a look at Castle.Facilities.AutomaticTransactionManagement.TransactionFacility for a nice way of handling transactions using AOP and the intercepting abilities of DynamicProxy2. The transaction facility integrated with System.Transcations and System.EnterpriseServices is you are using the distributed transaction coordinator (COM-component) for managing transactions. Also, there are multiple examples of p/invoke into the kernel to take care of the TxF and TxR components of the Vista-kernel (aka Server 2008) which allow you to use transactions on NTFS and on the registry, thereby making sure CRUD you do is ACID, which also nicely integrates with System.Transactions for creating nested transactions.

不变验证中的用法您还可以通过将一些属性附加到您的参数,将它们用于合同设计.

Usages in invariant verification You can also use them for design by contract, by appending some attributes to your parameters.

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

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

The problem with this at the moment is the overhead of attaching this meta-data and checking it at runtime. However, you could specify the constraint-checking aspect only to be applied when you're compiling with DEBUG and then this meta data-wouldn't lead to much deterioration in performance.

如果您想进入公理证明,请查看 Sing#/Spec#,因为它更正式,而且工作由编译器完成.

If you are looking to get into axiomatic proofs, have a look at Sing#/Spec# instead, since that's more formal and the work is done by the compiler.

注意事项要注意的最重要的一点是,如果一个问题,即在您的方法之前或之后运行的某些代码段正在改变控制流,可能返回一个意外的类型,返回太早或一般不按照您正在调用的方法的意图可能会出现难以调试的错误.

Things to be aware of The most important point to be aware of is that if a concern, i.e. some piece of code that runs before or after your method is altering the control-flow, possibly returning an unexpected type, returning too early or in general doesn't behave along the intents of the method you were calling you may get errors which are hard to debug.

另外,当心从属性中抛出异常,因为你永远不知道何时或从哪个程序集发生反射;对你的属性的反思可能不会在你期望的时候发生.当我在属性中附加类型并仔细检查它们时,这发生在我身上.

Also, beware of the throwing of exceptions from attributes, because you never know when or from what assembly, reflection occurrs; the reflection on your attribute may not happen when you expect to. This happened to myself when I was attaching types in attributes and carefully checking them.

还要注意这样一个事实,即您在添加全局切入点"时打开了一个可能的攻击媒介,如果有人访问该切入点,可用于重定向系统的大部分.

Also beware of the fact that you're opening a possible attack vector in adding global "point-cuts" which, if someone gets access to, can be used to redirect large portions of your system.

其他框架如果您有兴趣了解更多关于 AOP 的总体知识,我建议您查看 Rickard Öberg 在 Qi4J 上的介绍,这是一个非常好的框架在用于 AOP 的 Java 中(Java 的对象继承语义略有不同,但这使得在 C#/F#/Nermle/Boo 中使用起来有点棘手.

Other frameworks If you are interested in learning more about AOP in general I suggest you check out Rickard Öberg's presentations on Qi4J, it's a very good framework in Java for AOP (java has slightly different object-inherited semantics though which makes a wee bit tricker to use in C#/F#/Nermle/Boo whatever.

AOP + 插件将面向方面的编程与运行时生成的程序集(例如 dynamicproxy2 创建的程序集)一起使用的另一个有趣的可能性是,您还可以使用它们来包装跨越应用程序边界的对象,从而简化附加管道的创建.我曾私下希望微软在为 3.5 创建插件框架时会使用它,但不幸的是,他们选择了静态代码生成方式,这导致开发人员在创建插件时产生了相当大的开销.问题是,除非卸载完整的 AppDomain,否则无法再次卸载加载到 AppDomain 中的不仅仅是反射"类型,因此您需要 1) 反映插件而不加载它以查看它的功能,除非您允许编写或生成大量手动元数据(并相信这一点)和 2)一些对象来保存您的对象的句柄,以便它不会被 GCed 并且您不知道类型(因此 IContract 程序集和 AddInHandle 类)——这可能可以通过动态代理/AOP 以一种很好的方式完成.

AOP + AddIns Another interesting possibility in using aspect oriented programming with runtime-generated assemblies such as those dynamicproxy2 creates, is that you can also use them to wrap objects that cross application boundaries, thereby simplifying the creation of a add-in-pipeline. I had secretly hoped that Microsoft would use this when they created their AddIn-framework for 3.5, but they chose to go the static code-gen way unfortunately, leading a a rather big overhead in creating add-ins, for the developer. The problem is that a type loaded for "more than reflection" into an AppDomain can't be unloaded again unless the complete AppDomain is unloaded, so you need 1) to reflect on the plugin without loading it to see what it is capable of unless you allow for lots of manual meta-data to be written or generated (and believe in that) and 2) some object to hold the handle to your object so that it's not GCed and you don't know the type (hence the IContract assembly and AddInHandle-class) -- this could probably be done in a nice way with a dynamic proxy/AOP.

使用 AOP 进行全局垃圾收集 ...在公共语言基础架构上的 linux/windows 上运行的分布式系统中.这篇论文有点难下载,所以我把它上传到我的服务器所以我知道在哪里是的.

Using AOP for global garbage collection ... in a distributed system running on linux/windows on the common language infrastructure. The paper was a bit hard to download so I uploaded it to my server so I know where it is.

后脚本(如果您在 CLR 上使用非标准语言而不是 DLR IL-weaving 可能会创建不符合标准的代码.我认为对于 F# 尤其有趣,因为使用很多非- 标准代码对语言的巨大好处(元组说)-如果你想得到编译时警告,你可以用 [assembly: CLSCompliant] 标记你的程序集.)

Post Scriptum (If you are using a non-standard language on the CLR and not the DLR IL-weaving might create non-standards compliant code. Especially interesting for F#, I think, because the use a lot of non-standard code to great benefit of the language (tuples say) -- you could mark your assembly with [assembly: CLSCompliant] if you want to get compile-time warnings of this.)

这篇关于有关面向方面编程的帮助和信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆