C# 属性和 AOP 范式

5
我希望了解C#自定义属性和AOP框架(如PostSharp)的使用区别。如何选择它们之间的差异?

1
AOP是一种编程范式,而属性是C#(或任何其他使用它们的语言)的实现细节。它们处于两个不同的层面。实现AOP的一种方法是使用属性,但AOP是一个更广泛的概念。 - Yuval Itzchakov
1个回答

7

自定义属性是在代码元素上声明元数据的方式,其他系统元素可以理解它,包括编译器、AOP框架、验证引擎等...

PostSharp执行IL(中间语言)织入,例如,在编译后,它基于配置/属性在程序集中某些点注入IL。例如,您可以向方法添加自定义属性,并在编译期间,PostSharp将编写IL以拦截此方法并在运行时为您提供行为。

https://www.postsharp.net/aop.net/msil-injection

PostSharp是实现AOP的一种方式,还有许多其他方式,包括动态代理(例如Castle.Core),它可以通过提供要扩展的类的动态子类来在运行时拦截方法。

在这两个示例中,属性可以为您提供配置这些功能的手段。

例如,您有一个方法:

public int Add(int x, int y)
{
     return x + y;
}

如果您想为该方法提供日志记录或诊断功能,可以手动添加以下代码(log是一个虚构的日志记录API):

public int Add(int x, int y)
{
     log.Enter("Add", x, y);
     log.Leave("Add", x, y);
     return x + y;
}

当考虑方法的复杂性和单一职责原则时,您会分散方法的目的并开始让情况变得混乱。

理想情况下,您希望能够在运行时/编译时添加此行为,并且通常不仅适用于单个方法,这就成为一个横切关注点,例如您想要记录所有内容。

因此,您最终需要一种通知系统的方式,告诉它您要将日志应用于Add方法。其中一种方便的方法是使用属性对方法进行标记:

[Log]
public int Add(int x, int y)
{
    return x + y;
}

我们在Add方法中添加了元数据([Log]属性)来指示我们要记录此方法(并恢复为不违反单一责任原则的方法),然而仅靠属性本身是相对无意义的。
需要的是一些解释自定义属性的东西,并提供拦截方法调用并添加log.Enter、log.Leave调用的机制。这就是我们选择像PostSharp或Dynamic Proxies等AOP框架的地方。

不错的回答。我可以建议将“自定义属性是声明方式”的段落移到你的回答开头吗?那确实是这里的关键所在-属性可以用于各种各样的事情,但本身并不执行任何操作。 AOP框架使用属性来实际执行某些操作。 - BJ Myers
PostSharp不是免费的。 - xiaoyifang

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