C# (.Net) 的面向方面编程 (AOP) 解决方案及其特性

发布于 2024-10-17 13:16:51 字数 819 浏览 3 评论 0原文

我想在这里询问 3 条信息:

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

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

  3. 考虑以下标准:C#(.Net)最佳 AOP 解决方案是什么(在您看来):

    1. 它的工作原理应该与 AspectJ 类似,并且具有类似的语法
    2. 使用简单:不需要 XML 配置 - 只需编写一些常规类、一些方面类并编译以将它们编织在一起,然后运行。
    3. 应包含 AspectJ 的所有功能。支持泛型。
    4. 解决方案应该稳定、广泛使用和维护。
    5. 应该提供二进制文件的编织(因此可以使用)或 C# 源代码。
    6. 用于可视化的 GUI 工具(甚至更好 - VS 的插件)是一个优势。

我认为,如果某个东西满足 3 中的大部分标准,那么它就是通用解决方案的候选者。我无法找到任何现有的解决方案是否适合我的需求。

I would like to ask for 3 information here:

  1. There is no integrated solution for Aspect Oriented Programing (AOP) in C# (.Net) from Microsoft is that correct ? Is there any such solution under development or planned ?

  2. What solutions are there that allow Aspect Oriented Programing (AOP) to be used in C# (.Net) ? What are they advantages/disadvantages ? I haven't find any comprihensive list that would contain all avatable options and some information for me to decide which is the one to use. The closest is this list.

  3. What is (in your opinion) the best AOP solution for C#(.Net) considering following criteria:

    1. it schould work similar to AspectJ and has similar syntax
    2. simplicity of use: no XML configuration should be needed - just write some regular classes, some aspect classes and compile to weave it all together, then run.
    3. should include all features of AspectJ. Support for generics.
    4. solution should be stable, widely used and mainteined.
    5. should offer weaving of binaries (so could be used ) or C# source code.
    6. GUI tool for visualising (or even better - plugin to VS) is an advantage.

I think that if something fullfils most of criteria in 3. then it is a candidate for a generaly used solution. And I cannot find anywhere if some of existing solutions fits to my needs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲世九天 2024-10-24 13:16:51

正如 Adam Rackis 指出的那样,Post# 是最佳选择,它与 .NET 平台上的 AspectJ 非常接近。

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

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

  1. 不,甚至不接近,AspectJ是一种语言,Post#可以使用自定义切入点,但最常见的是使用属性来装饰要切入点的方法(呃..语法?)

  2. check

  3. 除了语言支持之外的所有内容

  4. check

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

  6. 受限,编织器将生成智能感知信息并显示哪些方法受到影响

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

关于不同的方法,有以下几种:

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

  2. 真实代理/MarshallByRefObject。
    基于远程基础设施。
    要求您的类继承基类。
    性能极差且没有“自拦截”

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

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

[编辑] 我忘记将其添加到列表中:

  1. 接口代理
    与动态代理类似,但不是将拦截代码应用于子类,而是将拦截代码添加到运行时生成的接口代理中。
    也就是说,您获得一个实现给定接口的对象,然后该对象将对任何接口方法的每次调用首先委托给 AOP 拦截代码,然后将调用委托给真实对象。
    也就是说,这里有两个对象在起作用,代理和主题(您的真实对象)。

客户端 ->接口代理-> AOP拦截-> Target/Subject

这就是 Spring 所做的事情。

1) 和 3) 是最常见的。
它们都有优点和缺点:

编译后:

优点:

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

缺点:

  • 不能基于上下文应用方面,也就是说,如果一个类型受到影响,整个应用程序都会受到影响。

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

动态代理:

优点:

  • 上下文,一种类型可以根据上下文应用不同的方面。

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

缺点:

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

  • 必须使用工厂创建对象

As Adam Rackis points out, Post# is the way to go, it is as close you will get to AspectJ on the .NET platform.

Main differences is obviously that AspecJ has language support for aspects while Post# is a post compile weaver for .NET assemblies.
(thus no language integration)

However, Post# can use join points such as field access, try catch blocks, both calls and functions (that is, caller and callee)

  1. No not even close, AspectJ is a language, Post# can use custom pointcuts but the most common is to use attributes to decorate methods to be pointcutted(eh..grammar?)

  2. check

  3. everything but language support

  4. check

  5. check - it is a post compile weaver

  6. limited, the weaver will generate intellisense information and show what methods have been affected

If you want a .NET language that supports aspects, check out http://aspectsharpcomp.sourceforge.net/samples.htm

Regarding different approaches, there are a few:

  1. Post compile weaving , this is what Post# does.
    It simply mangles the .NET assembly and injects the aspect code.

  2. Real Proxy / MarshallByRefObject.
    Based on remoting infrastructure.
    Requires your classes to inherit from a base class.
    Extremely bad performance and no "self interception"

  3. Dynamic Proxy.
    This is what my old library NAspect used.
    you use a factory to create a subclass of the type on which you want to apply aspects.
    The subclass will add mixin code using interfaces and override virtual methods and inject interceptor code.

  4. Source code weaving.
    As the name implies, it transforms your source code before compilation.

[edit] I forgot to add this one to the list:

  1. Interface proxies
    Similar to Dynamic Proxy, but instead of applying the interception code to a subclass, the interception code is added to a runtime generated interface proxy.
    That is, you get an object that implements a given interface, this object then delegates each call to any of the interface methods first to the AOP interception code and then it delegates the call to the real object.
    That is, you have two objects at play here, the proxy and the subject(your real object).

Client -> Interface Proxy -> AOP interception -> Target/Subject

This is AFAIK what Spring does.

1) and 3) are the most common.
They both have pros and cons:

Post Compilation:

Pros:

  • Can point cut pretty much everything, static , sealed, private
  • Objects can still be created using "new"

Cons:

  • Can not apply aspects based on context, that is , if a type is affected, it will be affected for the entire application.

  • Pointcutting private, static, sealed constructs may lead to confusion since it breaks fundamental OO rules.

Dynamic Proxy:

Pros:

  • Contextual, one typ can have different aspects applied based on context.

  • Easy to use, no configuration or build steps.

Cons:

  • Limited pointcuts, only interface members and virtual members can be intercepted

  • must use factory to create objects

红ご颜醉 2024-10-24 13:16:51

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 来可视化此类方面

1 - Correct

2 - PostSharp is an outstanding AOP library for C#

3 - I don't know how AspectJ works, but with PostSharp you simply define your aspects as attributes, and then decorate your methods with said attributes.

Here's an example of an aspect that wraps a method call with a try catch, and logs any exceptions that get thrown:

[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;
    }
}

So point by point

1 - I don't know

2 - check

3 - I don't know
4 - check

5 - check (pretty sure)

6 - no - not sure how you would use a GUI for visualizing aspects like this

锦爱 2024-10-24 13:16:51

问题在于您正在比较不同的语言并试图将方钉强行插入圆孔中。

对于 Java,由于语言的限制,AspectJ 满足了这一需求,但 .NET 不一定有这些限制,JVM 没有,但 Java 有。

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

您可以使用 C# 中的扩展方法通过交换程序集来更改行为,这样您就有一个具有记录到文件的扩展的程序集,然后将该程序集交换为具有相同命名空间的另一个程序集,该程序集会将数据发送到 Web 服务,或者做一个空操作。

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

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

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

更新:

我希望让我的答案更简短,但是对 AOP 的一些了解可能有助于为我的答案添加上下文。

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

但有了 AspectJ,就有更多选择。例如,您销售一个存储密码的程序。 A公司使用IDEA,B公司使用AES。为了适应,您更改了运行时使用的代码,这样您就不必冒险重新编译代码并引入新的错误,并且它已更改,因此每当有人调用 getPassword()新的代码用于解密它。

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

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

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

因此,由于这些虚拟机上可用的动态或强类型函数语言,减少了对面向方面编程的需求,但是,您可以用多语言解决方案来交换使用方面的复杂性。

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

一些想法关于 .NET 上的 AOP,您可以阅读 Code mangling AOP vs. Runtime Proxy AOP
, http://rogeralsing.com/2008 /01/08/code-mangling-aop-vs-runtime-proxy-aop/

The problem is that you are comparing different languages and trying to force square pegs into round holes.

For Java AspectJ fills a need due to limits in the language, but .NET doesn't necessarily have these limitations, as the JVM doesn't, but Java does.

For example, you can use IronPython or IronRuby (in addition to others) to write assemblies that are very dynamic, so you can write a DSL (domain specific language) that will enable a user to add in code that is not XML, but will change how the program operates.

You can use extension methods in C# to change the behavior by swapping out assemblies, so you have an assembly that have extensions that log to a file, then you swap that assembly for another one with the same namespace that will send the data to a webservice, or do a noop.

But, there are limitations to this that may be hard to overcome, such as being able to use one aspect to do something in every function called, such as using cflow (http://www.eclipse.org/aspectj/doc/released/progguide/semantics-pointcuts.html), but that may be because I haven't thought enough about how to do it.

My point is not to give a complete explanation of how .NET doesn't need AspectJ, but to show that there are ways to get the behavior you may expect without using AOP.

For apps running on the JVM you can use Groovy, Clojure, JRuby and Scala, for example, to work around the limitations of Java.

UPDATE:

I was hoping to keep my answer shorter, but some understanding of AOP may be useful to add context to my answer.

Aspect Oriented Programming (AOP) is a different programming paradigm, for functionality that cuts across classes, such as logging. Logging is a common situation, where you may want to log all SQL queries being used, so, rather than copying code from place to place, you put it in one place and it gets put into everywhere you specify, so, if you decide later to change where the logging goes, you change it in one place.

But with AspectJ there are more options. For example, you sell a program that stores passwords. Company A uses IDEA, company B uses AES. In order to adapt you change the code that is used at runtime so you don't have to risk recompiling the code and introducing new bugs, and it is changed, so that whenever someone calls getPassword() the new code is used to decrypt it.

You can also add functionality to an existing class, so I would put methods into interfaces so that everything that used that interface now had access to the functions, so the methods were now concrete, in the interface.

But, by using other languages that are on the .NET and JVM you can do all of these, with the same modularity, by carefully picking which language to use. For example, in Java you can access classes written in Groovy or Scala, so you can get more flexibility with these languages and still have the main app in Java.

In C# you can use F#, IronPython or IronRuby, for example, to get this functionality, or, for some cases you can use C#.

So the need for aspect oriented programming is lessened due to these dynamic, or strongly-typed functional languages, being available on these virtual machines, but, you trade the complexity of working with aspects with having a multi-language solution.

For more on AOP, IBM had some incredible articles about using it, with their AOP@Work series: http://www.ibm.com/developerworks/views/java/libraryview.jsp?search_by=AOP@work:

For some thoughts on AOP on .NET you can read Code mangling AOP vs. Runtime Proxy AOP
, http://rogeralsing.com/2008/01/08/code-mangling-aop-vs-runtime-proxy-aop/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文