针对C#(。Net)的面向方面编程(AOP)解决方案及其功能

时间:2011-02-15 01:35:36

标签: c# .net aop

我想在这里要求提供3条信息:

  1. C#(。Net)中的面向方面编程(AOP)没有集成解决方案来自Microsoft 的是正确的吗?是否有任何此类解决方案正在开发或计划中?

  2. 有什么解决方案允许在C#(。Net)中使用面向方面编程(AOP)?它们优点/缺点是什么?我没有找到任何包含所有可用选项的综合列表和一些信息供我决定使用哪一个。最接近的是this list

  3. 考虑到以下标准 p>

    1. 它的工作方式与AspectJ类似,语法类似
    2. 使用简单:不需要XML配置 - 只需编写一些常规类,一些方面类并编译以将它们编织在一起,然后运行。
    3. 应包含AspectJ的所有功能。支持泛型。
    4. 解决方案应该稳定,广泛使用和维护。
    5. 应该提供编织二进制文件(因此可以使用)或C#源代码。
    6. 用于可视化(甚至更好 - 插件到VS)的GUI工具是一个优势。
  4. 我认为,如果某些内容完全符合3中的大多数标准,那么它就是常用解决方案的候选者。如果某些现有解决方案符合我的需求,我无处可寻。

3 个答案:

答案 0 :(得分:18)

正如Adam Rackis指出的那样,Post#是要走的路,你可以在.NET平台上接近AspectJ。

主要区别显然是AspecJ对方面有语言支持,而Post#是.NET程序集的后编译编织器。 (因此没有语言整合)

但是,Post#可以使用连接点,例如字段访问,尝试catch块,调用和函数(即调用者和被调用者)

  1. 甚至没有关闭,AspectJ是一种语言,Post#可以使用自定义切入点,但最常见的是使用属性来装饰要切入的方法(eh..grammar?)

  2. 检查

  3. 除语言支持外的一切

  4. 检查

  5. 检查 - 这是一个后编译编织器

  6. 有限,编织者将生成智能感知信息并显示受影响的方法

  7. 如果您需要支持方面的.NET语言,请查看http://aspectsharpcomp.sourceforge.net/samples.htm

    关于不同的方法,有一些:

    1. 编译后编织,这就是Post#的作用。 它只是破坏.NET程序集并注入方面代码。

    2. Real Proxy / MarshallByRefObject。 基于远程基础设施。 要求您的类继承自基类。 表现极差,没有“自我拦截”

    3. 动态代理。 这就是我的旧库NAspect所使用的。 您使用工厂来创建要应用方面的类型的子类。 子类将使用接口添加mixin代码并覆盖虚拟方法并注入拦截器代码。

    4. 源代码编织。 顾名思义,它会在编译之前转换您的源代码。

    5. [edit]我忘了把这个添加到列表中:

      1. 接口代理 与动态代理类似,但不是将拦截代码应用于子类,而是将拦截代码添加到运行时生成的接口代理中。 也就是说,你得到一个实现给定接口的对象,然后该对象首先将对每个接口方法的调用委托给AOP拦截代码,然后将调用委托给真实对象。 也就是说,你在这里有两个对象,代理和主题(你的真实对象)。
      2. Client -> Interface Proxy -> AOP interception -> Target/Subject

        这是AFAIK Spring的功能。

        1)和3)是最常见的。 他们都有利有弊:

        编辑后:

        优点:

        • 可以点几乎所有东西,静态,密封,私密
        • 仍然可以使用“new”
        • 创建对象

        缺点:

        • 无法根据上下文应用方面,也就是说,如果某个类型受到影响,它将受到整个应用程序的影响。

        • 切入私有的,静态的,密封的结构可能会导致混淆,因为它违反了基本的OO规则。

        动态代理:

        优点:

        • 在上下文中,一个typ可以根据上下文应用不同的方面。

        • 易于使用,无需配置或构建步骤。

        缺点:

        • 有限的切入点,只能拦截接口成员和虚拟成员

        • 必须使用工厂来创建对象

答案 1 :(得分:4)

1 - 正确

2 - PostSharp是C#

杰出 AOP库

3 - 我不知道AspectJ是如何工作的,但是使用PostSharp,您只需将方面定义为属性,然后使用所述属性修饰方法。

这是一个使用try catch包装方法调用的方面的示例,并记录任何抛出的异常:

[Serializable]
public class ErrorAspectAttribute : OnMethodBoundaryAspect {
    private bool Notify;

    public ErrorAspectAttribute(bool notifyUser = true) {
        this.Notify = notifyUser;
    }

    public override void OnException(MethodExecutionEventArgs args) {
        ErrorLoggerUtil.LogException(args.Exception);           

        if (Notify)
            MessageBox.Show("An error has occurred.  Please save blah blah blah", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

        args.FlowBehavior = FlowBehavior.Return;
    }
}

一点一点地

1 - 我不知道

2 - 检查

3 - 我不知道 4 - 检查

5 - 检查(非常肯定)

6 - 不 - 不确定如何使用GUI来显示像这样的方面

答案 2 :(得分:0)

问题是你正在比较不同的语言并试图将方形钉子强制成圆孔。

对于Java,由于语言的限制,AspectJ填补了需求,但.NET不一定具有这些限制,因为JVM没有,但Java确实如此。

例如,您可以使用IronPython或IronRuby(除了其他人)来编写非常动态的程序集,因此您可以编写一个DSL(特定于域的语言),使用户能够添加非XML的代码,但会改变程序的运作方式。

您可以使用C#中的扩展方法通过交换程序集来更改行为,因此您有一个具有登录到文件的扩展的程序集,然后您将该程序集交换为另一个具有将发送数据的相同名称空间的程序集到网络服务,或做一个noop。

但是,有一些限制可能难以克服,例如能够使用一个方面在所调用的每个函数中执行某些操作,例如使用cflow(http://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html),但这可能是因为我对如何做到这一点还不够。

我的观点不是要完整解释.NET如何不需要AspectJ,而是要说明如何在不使用AOP的情况下获得您可能期望的行为。

对于在JVM上运行的应用程序,您可以使用Groovy,Clojure,JRuby和Scala来解决Java的限制。

<强>更新

我希望能够缩短答案,但是对AOP的一些理解可能有助于为我的答案添加背景。

面向方面编程(AOP)是一种不同的编程范例,用于跨越类的功能,例如日志记录。日志记录是一种常见的情况,您可能希望记录所有正在使用的SQL查询,因此,不是将代码从一个地方复制到另一个地方,而是将它放在一个地方并将其放入您指定的任何位置,因此,如果您稍后决定要更改日志记录的位置,请在一个位置进行更改。

但是使用AspectJ还有更多选择。例如,您销售存储密码的程序。 A公司使用IDEA,B公司使用AES。为了适应你改变运行时使用的代码,所以你不必冒着重新编译代码和引入新bug的风险,并且它被改变了,所以每当有人调用getPassword()新代码用于解密它。

您还可以向现有类添加功能,因此我将方法放入接口,以便使用该接口的所有内容现在都可以访问这些函数,因此这些方法现在在界面中具体了。

但是,通过使用.NET和JVM上的其他语言,您可以通过仔细选择要使用的语言,以相同的模块化完成所有这些语言。例如,在Java中,您可以访问用Groovy或Scala编写的类,这样您就可以使用这些语言获得更大的灵活性,并且仍然拥有Java中的主应用程序。

在C#中,您可以使用F#,IronPython或IronRuby来获得此功能,或者,在某些情况下,您可以使用C#。

因此,在这些虚拟机上可以使用这些动态或强类型的函数语言,因此减少了面向方面编程的需求,但是,您需要使用多语言解决方案来处理使用方面的复杂性。 / p>

有关AOP的更多信息,IBM有一些关于使用它的令人难以置信的文章,其 AOP @ Work 系列:http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=AOP@work:

关于.NET上AOP的一些想法,您可以阅读代码修改AOP与运行时代理AOP ,http://rogeralsing.com/2008/01/08/code-mangling-aop-vs-runtime-proxy-aop/