我想知道使用 C# 自定义属性和 AOP 框架(如 PostSharp)之间的区别。
如何在它们之间进行选择?
请您参考如下方法:
自定义属性是在代码元素上声明元数据的方法,这些元素可以被系统的其他元素理解,包括编译器、AOP 框架、验证引擎等。
PostSharp 执行 IL(中间语言)编织,例如在编译后它会根据配置/属性在程序集中的某些点注入(inject) 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;
}
并且您想通过手动添加此代码来为此方法提供日志记录或诊断(日志是一个假设的日志记录 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] Attribute)中,以表明我们要记录此方法(并恢复为不违反单一职责原则的方法),但是该属性本身相对没有意义。
需要的是解释自定义属性并提供拦截方法调用并添加 log.Enter、log.Leave 调用的机制。这是我们选择 PostSharp 或动态代理或其他 AOP 框架的地方。