C# 如何知道代码是否在TransactionScope中?
知道代码块是否在TransactionScope内的最佳方法是什么?C# 如何知道代码是否在TransactionScope中?,c#,.net,transactionscope,C#,.net,Transactionscope,知道代码块是否在TransactionScope内的最佳方法是什么? Transaction.Current是一种切实可行的方式吗?还是有任何微妙之处? 是否可以使用反射访问内部ContextData.CurrentData.CurrentScope(在System.Transactions中)?如果是,如何处理?事务。当前的应该是可靠的;我刚刚检查过,在这种情况下,受抑制的事务也可以正常工作: Console.WriteLine(Transaction.Current != null); //
Transaction.Current是一种切实可行的方式吗?还是有任何微妙之处?
是否可以使用反射访问内部ContextData.CurrentData.CurrentScope(在System.Transactions中)?如果是,如何处理?
事务。当前的
应该是可靠的;我刚刚检查过,在这种情况下,受抑制的事务也可以正常工作:
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中)。通过反射也可以获得这些信息,但发射IL的速度比反射快100倍
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);
}
private Func\u getCurrentScopeDelegate;
布尔伊森斯代特交易镜
{
得到
{
如果(_getCurrentScopeDelegate==null)
{
_getCurrentScopeDelegate=CreateGetCurrentScopeDelegate();
}
TransactionScope ts=_getCurrentScopeDelegate();
返回ts!=null;
}
}
私有函数CreateGetCurrentScopeDelegate()
{
DynamicMethod getCurrentScopeDM=新的DynamicMethod(
“GetCurrentScope”,
类型(交易范围),
无效的
this.GetType(),
正确的);
Type t=typeof(Transaction.Assembly.GetType(“System.Transactions.ContextData”);
MethodInfo getCurrentContextDataMI=t.GetProperty(
“当前数据”,
BindingFlags.NonPublic | BindingFlags.Static)
.getMethod(true);
FieldInfo currentScopeFI=t.GetField(“CurrentScope”,BindingFlags.NonPublic | BindingFlags.Instance);
ILGenerator gen=getCurrentScopeDM.GetILGenerator();
gen.Emit(操作码.Call,getCurrentContextDataMI);
gen.Emit(操作码.Ldfld,电流范围fi);
gen.Emit(操作码Ret);
return(Func)getCurrentScopeDM.CreateDelegate(typeof(Func));
}
[测试]
公共无效IsInsideTransactionScopeTest()
{
Assert.IsFalse(IsInsideTransactionScope);
使用(新TransactionScope())
{
Assert.IsTrue(IsInsideTransactionScope);
}
Assert.IsFalse(IsInsideTransactionScope);
}
有一个更新版本,使用的表达式不需要系统。事务
参考
internal static class TransactionScopeHelper
{
static Func<object?> _getCurrentScopeDelegate = GetTransactionScopeFunc();
public static bool IsInsideTransactionScope
{
get
{
var ts = _getCurrentScopeDelegate();
return ts != null;
}
}
static Func<object?> GetTransactionScopeFunc()
{
var assembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().Name == "System.Transactions");
if (assembly != null)
{
var t = assembly.GetType("System.Transactions.ContextData");
var currentDataProperty = t.GetProperty("TLSCurrentData", BindingFlags.NonPublic | BindingFlags.Static);
if (currentDataProperty != null)
{
var body = Expression.MakeMemberAccess(null, currentDataProperty);
var lambda = Expression.Lambda<Func<object?>>(body);
return lambda.Compile;
}
}
return () => null;
}
}
内部静态类TransactionScopeHelper
{
静态Func_getCurrentScopeDelegate=GetTransactionScopeFunc();
公共静态布尔IsInsideTransactionScope
{
得到
{
var ts=_getCurrentScopeDelegate();
返回ts!=null;
}
}
静态Func GetTransactionScopeFunc()
{
var assembly=AppDomain.CurrentDomain.GetAssemblys()
.FirstOrDefault(a=>a.GetName().Name==“System.Transactions”);
如果(程序集!=null)
{
var t=assembly.GetType(“System.Transactions.ContextData”);
var currentDataProperty=t.GetProperty(“TLSCurrentData”,BindingFlags.NonPublic | BindingFlags.Static);
如果(currentDataProperty!=null)
{
var body=Expression.MakeMemberAccess(null,currentDataProperty);
var lambda=表达式.lambda(主体);
返回lambda.Compile;
}
}
return()=>null;
}
}
我的意思是,即使我们不在TransactionScope中,也可以设置Transaction.Current属性。如果TransactionScope已完成,但仍未处理,Syste.Transactions.Transaction.Curre会抛出一个例外。我想知道您是否更改了“可靠”的定义如果Transaction.Current不可靠,为什么.Net开发人员不将其保留为只读?你看过它的实现吗?它出现在.Net 4.5中,“CurrentData”被重命名为“TLSCurrentData”@JeremyRosenberg I concur。今天是我第二次遇到巫毒代码,它反映在框架内部,带有魔法字符串,只有当它们发生变化时才会出现爆炸。@ChrisMcKelt你在哪里看到的?网上有没有关于这一变化的参考资料?