这似乎是一个基本的东西......
这是(许多)易于理解概念但根本不易于实现的事物之一。
根据Oded 的回答,.NET 中的属性不执行任何操作。它们仅存在以便其他代码(或开发人员)稍后可以查看它们。把它想象成一个花哨的评论。
考虑到这一点,您可以像这样编写属性
public class AtomicAttribute : Attribute { }
现在最困难的部分是,您必须编写一些代码来扫描该属性,并更改代码的行为。
鉴于 C# 是一种编译语言,并且鉴于 .NET CLR 的规则,理论上有 3 种方法可以做到这一点
挂钩到 C# 编译器,并使其在看到该属性时输出不同的代码。
这似乎很好,但现在根本不可能。也许
Roslyn
项目将来可能会允许这样做,但现在,你不能这样做。
在 C# 编译器将其转换为 MSIL后,编写将扫描 .NET 程序集的内容,并更改 MSIL。
这基本上就是PostSharp所做的。扫描和重写 MSIL很难。有诸如Mono.Cecil 之类的库可以提供帮助,但这仍然是一个非常困难的问题。它也可能会干扰调试器等。
使用 .NET Profiling API 在程序运行时监视程序,每次看到具有该属性的函数调用时,将其重定向到其他包装函数。
这可能是最简单的选择(尽管仍然非常困难),但缺点是您的程序现在必须在探查器下运行。这在您的开发 PC 上可能没问题,但如果您尝试部署它会导致大问题。此外,使用这种方法可能会对性能造成很大影响。
在我看来,最好的办法是创建一个设置事务的包装函数,然后将其传递给执行实际工作的 lambda。像这样:
public static class Ext
{
public static void Atomic(Action action)
{
using(var scope = new TransactionScope())
{
action();
scope.Commit();
}
}
}
.....
using static Ext; // as of VS2015
public void Foo()
{
Atomic(() => {
// foo logic
}
}
这个花哨的计算机科学术语是高阶编程