如何知道代码是否在TransactionScope中?

知道代码块是否在TransactionScope内的最佳方法是什么?
Transaction.Current是一种可行的方式,还是有任何细微之处?
是否可以使用reflection访问内部ContextData.CurrentData.CurrentScope(在System.Transactions中)? 如果有,怎么样?

Transaction.Current应该是可靠的; 我刚检查过,在这种情况下,抑制交易的效果也很好:

 Console.WriteLine(Transaction.Current != null); // false using (TransactionScope tran = new TransactionScope()) { Console.WriteLine(Transaction.Current != null); // true using (TransactionScope tran2 = new TransactionScope( TransactionScopeOption.Suppress)) { Console.WriteLine(Transaction.Current != null); // false } Console.WriteLine(Transaction.Current != null); // true } Console.WriteLine(Transaction.Current != null); // false 

这是更可靠的方式(正如我所说,Transaction.Current可以手动设置,并不总是意味着我们真的在TransactionScope中)。 也可以通过reflection获得这些信息,但发射IL的速度比reflection快100倍。

 private Func _getCurrentScopeDelegate; bool IsInsideTransactionScope { get { if (_getCurrentScopeDelegate == null) { _getCurrentScopeDelegate = CreateGetCurrentScopeDelegate(); } TransactionScope ts = _getCurrentScopeDelegate(); return ts != null; } } private Func CreateGetCurrentScopeDelegate() { DynamicMethod getCurrentScopeDM = new DynamicMethod( "GetCurrentScope", typeof(TransactionScope), null, this.GetType(), true); Type t = typeof(Transaction).Assembly.GetType("System.Transactions.ContextData"); MethodInfo getCurrentContextDataMI = t.GetProperty( "CurrentData", BindingFlags.NonPublic | BindingFlags.Static) .GetGetMethod(true); FieldInfo currentScopeFI = t.GetField("CurrentScope", BindingFlags.NonPublic | BindingFlags.Instance); ILGenerator gen = getCurrentScopeDM.GetILGenerator(); gen.Emit(OpCodes.Call, getCurrentContextDataMI); gen.Emit(OpCodes.Ldfld, currentScopeFI); gen.Emit(OpCodes.Ret); return (Func)getCurrentScopeDM.CreateDelegate(typeof(Func)); } [Test] public void IsInsideTransactionScopeTest() { Assert.IsFalse(IsInsideTransactionScope); using (new TransactionScope()) { Assert.IsTrue(IsInsideTransactionScope); } Assert.IsFalse(IsInsideTransactionScope); }