C# 属性和 Aop 范式

C# Attributes and Aop paradigm

我想知道使用 C# 自定义属性和使用 AOP 框架(如 PostSharp)之间的区别。 如何取舍?

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

PostSharp 执行 IL(中间语言)编织,例如,编译后它会根据 configuration/attributes 在程序集中的某些点注入 IL。例如,您可以将自定义属性添加到方法中,并且在编译期间 PostSharp 将编写 IL 来拦截此方法并在运行时为您提供行为。

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

PostSharp 是实现 AOP 的一种方法,还有许多其他方法,包括动态代理(例如 Castle.Core),它可以通过提供 [=44= 的动态子 类 在运行时拦截方法] 您希望延长。

在这两个示例中,属性都可以为您提供一种配置这些功能的行为的方法

比如你有一个方法:

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

在考虑方法复杂性和单一责任原则时,您会分散方法的目的,并且开始混淆水域。

理想情况下,您希望能够在 runtime/compile 时间添加此行为,并且通常对于不止一个方法,这将成为一个横切关注点,例如您想要记录所有内容。

所以您最终需要一种方法来通知系统您要将日志记录应用到 Add 方法。一种方便的方法是使用属性标记方法:

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

我们已将元数据添加到 Add 方法([Log] 属性)以指示我们要记录此方法(并恢复为不违反单一职责原则的方法),但是属性本身相对没有意义。

需要解释自定义属性并提供拦截方法调用和添加 log.Enter、log.Leave 调用的机制。这是我们选择类似 PostSharp 或动态代理或其他 AOP 框架的地方。