如何知道是否code是里面的TransactionScope?里面、code、TransactionScope

由网友(暮而归)分享简介:什么是知道如果code座里面的TransactionScope最好的方法是什么?是Transaction.Current一个realiable办法做到这一点,或有任何细微之处?是否有可能访问内部ContextData.CurrentData.CurrentScope(在System.Transactions的)与反...

什么是知道如果code座里面的TransactionScope最好的方法是什么? 是Transaction.Current一个realiable办法做到这一点,或有任何细微之处? 是否有可能访问内部ContextData.CurrentData.CurrentScope(在System.Transactions的)与反思?如果是的话,怎么办?

What is the best way to know if the code block is inside TransactionScope? Is Transaction.Current a realiable way to do it or there are any subtleties? Is it possible to access internal ContextData.CurrentData.CurrentScope (in System.Transactions) with reflection? If yes, how?

感谢你在前进。

推荐答案

下面是更可靠的方式(正如我所说,Transaction.Current可以手动设置,这并不意味着我们是真心的TransactionScope)。它也可能得到这个信息与反思,但IL冒落的作品比反射快100倍。

Here is more reliable way (as I said, Transaction.Current can be set manually and it doesn't always mean we are really in TransactionScope). It's also possible to get this information with reflection, but emiting IL works 100 times faster than reflection.

private Func<TransactionScope> _getCurrentScopeDelegate;

bool IsInsideTransactionScope
{
  get
  {
    if (_getCurrentScopeDelegate == null)
    {
      _getCurrentScopeDelegate = CreateGetCurrentScopeDelegate();
    }

    TransactionScope ts = _getCurrentScopeDelegate();
    return ts != null;
  }
}

private Func<TransactionScope> 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<TransactionScope>)getCurrentScopeDM.CreateDelegate(typeof(Func<TransactionScope>));
}

[Test]
public void IsInsideTransactionScopeTest()
{
  Assert.IsFalse(IsInsideTransactionScope);
  using (new TransactionScope())
  {
    Assert.IsTrue(IsInsideTransactionScope);
  }
  Assert.IsFalse(IsInsideTransactionScope);
}
阅读全文

相关推荐

最新文章