在.NET中,AOP的最佳实现方式是什么?

90

4
如果您提供所有AOP的链接,将有助于节省读者在Google上的时间。我希望这个问题/答案能够成为.NET中不同AOP选项的一个很好的概述。 - Ian Ringrose
11
52人投票认为这是一个有建设性的问题,5人投票认为不具建设性。谁做出了决定?至少版主应该修改或重新表述问题,但最好考虑大多数人的意见。 - Revious
2
@Revious 完全同意! - Legends
2
令人惊讶的是,像这样的问题被SO和人们投票为OT。这是一个非常有用的问题和技术,可以讨论和帮助社区,但却被简单地投票关闭,而一些老派、80年代风格的人却固守过去。SO,世界已经改变了。完全可以理解你想要回答具体问题的愿望,但至少在你的“关闭”标签中提供一个链接,告诉人们在哪里发布这样的问题。这将有很大帮助,避免这种愚蠢的情况发生。 - pixel
9年过去了,我认为现在很清楚为什么这个问题不是很有用。许多链接已经失效。 - Thomas Weller
5个回答

47

如果动态拦截能够满足您的需求,我认为Castle Dynamic Proxy是最佳选择。这个框架被许多其他想要提供AOP功能的框架内部使用。通常,现有的大多数IoC容器现在都提供一些动态拦截机制(例如Spring.NET、Castle Windsor、StructureMap等)。如果您已经使用过一个IoC容器,也许看看它提出的建议会更容易。

如果动态拦截无法满足您的需求(例如编织封闭类、拦截非虚拟调用等),那么您肯定需要静态编织。在这个领域,PostSharp是行业标准。

请注意,还存在Linfu,可以用于利用两种AOP的方式。


3
如果你想进行运行时 AOP,那么对此点赞(+1)。如果你想进行编译后 AOP,那么对 PostSharp 点赞(+1)。 - Krzysztof Kozmic
这个答案有更新吗?还是仍然有效?我特别想知道Spring.AOP如何与Castle和PostSharp相比。 - Evren Kuzucuoglu
2
不幸的是,PostSharp是一款商业产品。 - pixel
1
Postsharp是一款商业产品,不是免费的。请建议其他静态织入方案。 - Shivam Sachan
@ShivamSachan 只是因为某些东西是免费的,并不意味着它就是好的。大多数免费的 .net AOP 工具在 2-5 年前就已经停止更新了,而 PostSharp 仍然是最佳选择。 - Offler

15

“最好”是主观的。

首先,列出您需要的功能、体系结构等清单。然后寻找满足您需求的选项,避免引入不必要的复杂性。例如,有几个选项是面向接口的:您的代码目前是否是面向接口的?如果不是,那么PostSharp可能是更好的选择(被编织进原始类中)。但当然,PostSharp不能在运行时配置...因人而异。


1
你可以将你所说的重新表述为:“最好是主观的,我会列出一些框架的优缺点清单”。 - Revious

11
“最佳方式”当然是主观的,但对我而言,在.NET中进行面向方面编程的最佳方式是使用众所周知的设计技巧。例如,通过应用SOLID原则,您可以实现所需的灵活性和模块化,以允许添加横切关注点。如果您的设计正确,甚至可以在没有任何框架的情况下应用大多数横切关注点。认为OOP不适合进行AOP是一种谬论。
以下是一些指针:
  • 不要依赖具体实例,而是依赖抽象。
  • 不要在同一个类中混合横切关注点和业务逻辑。
  • 通过用实现这些关注点的类(装饰器)来包装带有业务逻辑的类来添加横切关注点。
  • 在设计中找到共同的构件,并使用相同类型的抽象来对它们进行建模。例如,请参阅此处此处

当您拥有正确的抽象时,向系统添加新的横切关注点只是编写一个新的装饰器类并将其包装在正确的实现周围的问题。如果抽象是通用的,则可以在大组类周围包装单个装饰器(这正是AOP所关注的内容)。

尽管动态代理和代码编织等技术可以使与设计不佳的应用程序更容易打交道,但良好的设计确实是无可替代的。迟早你会受到伤害。这并不意味着不能使用动态代理生成和代码编织等技术。但是,如果没有适当的应用程序设计,即使使用这些技术也只能帮助到一定程度。

2
AOP是抽象化的下一个层次。事实上,正是继承和组合的限制导致了AOP的出现。你见过Entlib异常块吗?与为每个调用数据库而调用该鬼东西以进行try-catch-log-throw相比,切面要干净得多。 - Sleeper Smith
2
如果你用异常块包装每个与数据库的调用,那么你做错了。这归结于良好的设计。始终如此。 - Steven
那么,除了捕获数据库异常,还有什么正确的方法吗? - OutOFTouch
2
@OutOFTouch:看一下这个SO问题的答案。 - Steven
2
@SleeperSmith:虽然我不确定“AOP是抽象的下一个层次”是什么意思,但我认为在没有使用AOP的情况下,无法保持大型系统的可维护性。我相信应用AOP。然而,AOP是一种范式;而不是一种工具。我同意继承的限制,但这不是组合的限制导致了AOP。缺乏适当的设计才会导致使用代码编织和动态代理工具。我使用装饰器来应用横切关注点。这是我应用AOP的首选方式。 - Steven
有时候我们需要使用AOP,可能是由于一些我们无法控制的第三方代码,而不是我们自己的代码。 - Hopeless

5

我不知道哪个是最好的,因为有很多框架,而且一天的时间不够试用它们。

我曾经使用过PostSharp,并惊喜地发现它非常容易上手。

我还研究了Castle Windsor和Spring.Net中的AOP,这种方法与编译时不同(运行时)。混合使用AOP和IoC似乎是有道理的。如果你还没有使用其中一个框架,那么开始工作会更加艰难,但不要让这阻止你。

对于新项目,我现在可能会使用Castle Windsor,但这主要是因为我也想使用IoC。如果我需要快速将AOP实现到现有代码库中,我会使用PostSharp。


4

Unity拦截已不再受支持:https://github.com/unitycontainer/unity - ssamko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接