我在调用上下文(CallContext.SetData(key,data)
)上放置了一些数据,其中数据是实现ILogicalThreadAffinative
的类型。它实现ILogicalThreadAffinative的原因是它必须在当前应用程序中的多个线程之间共享。
但是,该应用程序还会远程调用另一个服务,这就是问题所在。我的ILogicalThreadAffinative实现不可序列化,不应该。即使我将其标记为可序列化,远程应用程序也无法访问声明类型的程序集,因此无法对其进行反序列化。
那么如何在我的应用程序(AppDomain)中共享呼叫上下文数据,而不是与它碰巧需要与之交谈的每个外部应用程序共享?
答案 0 :(得分:6)
最终,我通过实现一个自定义IMessageSink解决了这个问题,我在插入远程调用的客户端格式化器之前插入了该IMessageSink。接收器在通过线路之前剥离呼叫上下文数据。以下是相关方法。
private static void SanitizeCallContext(IMessage msg)
{
var callContext = msg.Properties["__CallContext"] as LogicalCallContext;
if (callContext == null) return;
var sanitizedContext = (LogicalCallContext) callContext.Clone();
var prop = typeof (LogicalCallContext).GetProperty("Datastore",
BindingFlags.Instance | BindingFlags.NonPublic);
var dataStore = (Hashtable) prop.GetValue(sanitizedContext, null);
foreach (var key in dataStore.Keys.Cast<string>().ToArray())
sanitizedContext.FreeNamedDataSlot(key);
msg.Properties["__CallContext"] = sanitizedContext;
}
我不是特别喜欢这个解决方案。它看起来不仅仅是一点点hackish,但它是我能够提出的最好的解决方案。
答案 1 :(得分:3)
我的理解可能是错误的,将数据放入CallContext就足以使其流经多个线程。只有当您希望它在AppDomains中“自动”流动时,才需要实现ILogicalThreadAffinative(或通过LogicalSetData将数据放入CallContext)。所以看来如果你把你的数据放在CallContext但没有实现ILogicalThreadAffinative它应该做你想要的(在你的应用程序中流动但不跨越Appdomains)?
以下是我在CallContext和ILogicalThreadAffinative(或LogicalSetData)中找到的一些链接:
另一个显然引用上述链接信息的链接: http://dotnetmustard.blogspot.com/2008/08/identifying-differences-between.html
(有关log4net如何使用CallContext的解释,请参阅此链接中的Nicko Cadell的回复):
祝你好运!