2010-11-10 60 views
7

我已經在調用上下文(CallContext.SetData(key,data))上放置了一些數據,其中數據的類型實現了ILogicalThreadAffinative。它實現ILogicalThreadAffinative的原因是它必須在當前應用程序的多個線程之間共享。如何限制邏輯調用上下文的範圍

但是,應用程序也會對另一個服務進行遠程調用,這就是問題出現的地方。我的ILogicalThreadAffinative實現不可序列化,不應該是。即使我將它標記爲可序列化,遠程應用程序也無法訪問聲明類型的程序集,因此無法對其進行反序列化。

那麼如何在我的應用程序(AppDomain)中共享呼叫上下文數據,而不是每次需要與之通話的外部應用程序呢?

回答

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; 
    } 

我不特別喜歡這個解決方案。它似乎不僅僅是一個小小的詭計,但它是我能夠想出的最佳解決方案。

+0

我知道你已經找到了解決問題的方法,但是我最近發現Jeffrey Richter關於使用ExecutionContext.SuppressFlow來抑制邏輯線程數據流的書的摘錄。我不知道它是否適用於您描述的情況,但是,如果確實如此,它可能比您最終想出的更清晰:http://blogs.msdn.com/b/microsoft_press/archive/2010 /01/27/jeffrey-richter-excerpt-from-clr-via-c-third-edition.aspx – wageoghe 2011-01-04 18:59:31

+0

Wagaoghe,這看起來很有希望作爲替代解決方案。我想在遠程的情況下測試一下。它的缺點是必須在調用代碼內部以每個調用爲基礎進行設置。上述解決方案更多地面向方面,並且在某些方面更清晰。 – 2011-01-21 18:48:32

3

我的理解可能是錯誤的,即將數據放入CallContext足以使其跨​​多個線程流動。如果您希望跨AppDomain「自動」流動,則只需要實現ILogicalThreadAffinative(或通過LogicalSetData將數據放入CallContext中)。因此,如果你把你的數據放在CallContext中,但是不實現ILogicalThreadAffinative,它應該做你想做的事(在應用程序中流動,但不在Appdomains中)?

這裏有一些鏈接,我發現關於CallContext中和ILogicalThreadAffinative(或LogicalSetData):

http://social.msdn.microsoft.com/forums/en-US/netfxremoting/thread/aec8dda5-102e-44eb-9a41-0a5d8b8b96e9

另一個鏈接,顯然引用從上面的鏈接的信息: http://dotnetmustard.blogspot.com/2008/08/identifying-differences-between.html

(見力高Cadell在此鏈接中的回覆以解釋log4net如何使用CallContext):

http://www.l4ndash.com/Log4NetMailArchive%2Ftabid%2F70%2Fforumid%2F1%2Fpostid%2F15288%2Fview%2Ftopic%2FDefault.aspx

祝你好運!

+0

Wageoghe,謝謝你的回覆。但是,這些都沒有解決這個問題。所有這些討論都假定了一個邏輯執行線程,它可能會或不會穿過AppDomain,並在此基礎上討論CallContext與LogicalCallContext的區別。這種情況在多邏輯線程場景中處理CallContext與LogicalCallContext,如下所述:http://www.wintellect.com/CS/blogs/jeffreyr/archive/2010/09/27/logical-call-context-flowing -data-across-threads-appdomains-and-processes.aspx – 2010-11-12 12:28:26