我们遇到了Rebus的新(异步)版本的问题,旧版本不存在。
当处理rebus消息并尝试创建AppDomain和Instance以动态运行插件代码时,它总是给我一个例外。 为了使示例尽可能简单,我制作了一个测试方法:
public static void Test()
{
AppDomain ad = AppDomain.CreateDomain("Test");
Loader loader = (Loader)ad.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName);
}
class Loader : MarshalByRefObject
{
}
当我从'普通'代码调用方法时它可以工作但是当我从(异步)Rebus消息Handle方法调用它时,它给出了一个例外:
发现了System.Runtime.Serialization.SerializationException HResult = -2146233076消息=类型 汇编'Rebus中的'Rebus.Transport.DefaultTransactionContext', Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'未标记 可序列化。 Source = mscorlib StackTrace: 在System.AppDomain.CreateInstanceAndUnwrap(String assemblyName,String typeName) 位于d:\ Project \ App.Bus.MessageParser \ Process.cs中的App.Bus.MessageParse.Process.Test():第45行 位于d:\ Project \ App.Bus.MessageParser \ Process.cs中的App.Bus.MessageParse.Process.d__0.MoveNext():第28行InnerException:
关于这个问题的任何想法?
答案 0 :(得分:2)
Rebus将其事务上下文存储在AmbientTransactionContext.Current
中,该事务上下文由线程的逻辑调用上下文支持,当您await
时,它会自动流向continuation。
它也流向创建的appdomains,显然;)
我可以将DefaultTransactionContext标记为可序列化,但我担心您只会得到一个异常,告诉您事务上下文字典中的项目不可序列化。
我无法使事务上下文真正可序列化并保证它可以工作,所以 - 如果你需要在消息处理程序中创建一个appdomain - 我建议你暂时删除环境事务上下文 - 只记得放它又回来了:)
以下内容应该可以解决问题:
public async Task Handle(SomeMessage message)
{
var transactionContext = AmbientTransactionContext.Current;
AmbientTransactionContext.Current = null;
try
{
JuggleWithAppDomainsInHere();
}
finally
{
AmbientTransactionContext.Current = transactionContext;
}
}
如果你的应用程序中有一个常见的模式,你用appdomains做了什么,我建议你包装"删除和恢复环境-Rebus-事务"在IDisposable
内,您可以
using(new DismantleAmbientRebusStuff())
{
JuggleWithAppDomainsInHere();
}