2009-04-09 26 views
5

首先,我希望基於上下文的存儲在整個框架中保持一致!這就是說,我正在尋找一個優雅的解決方案,使這些屬性在ASP.NET,WCF和任何其他多線程.NET代碼中保持安全。這些屬性位於一些低級別的跟蹤幫助器中(如果您想知道爲什麼它們是內部的,則通過方法公開這些屬性)。尋求基於上下文的一致性存儲

我寧願沒有依賴不需要的程序集(如System.Web等)。我不想要求任何人使用此代碼來配置任何東西。我只是想要它的工作;)這可能是一個高的秩序,雖然...

任何人都有他們的袖子的招數? (我已經看到了春天的實現)

internal static string CurrentInstance 
    { 
     get 
     { 
      return CallContext.LogicalGetData(currentInstanceSlotName) as string; 
     } 
     set 
     { 
      CallContext.LogicalSetData(currentInstanceSlotName, value); 
     } 
    } 

    internal static Stack<ActivityState> AmbientActivityId 
    { 
     get 
     { 
      Stack<ActivityState> stack = CallContext.LogicalGetData(ambientActivityStateSlotName) as Stack<ActivityState>; 
      if (stack == null) 
      { 
       stack = new Stack<ActivityState>(); 
       CallContext.LogicalSetData(ambientActivityStateSlotName, stack); 
      } 

      return stack; 
     } 
    } 

更新

通過安全我的意思並不是同步的。關於這個問題的背景here

+0

我沒有太多的報價,但我也對這個問題感興趣。 FWIW我記得在某些源代碼倉庫(可能是Castle,NInject或NHibernate)中看到了幾種像IContext這樣的實現,我猜想它們可能會被直接插入到應用程序中。每個IContext實現使用不同的技術(CallContext,HttpContext,Thread.SetData等)。我不確切知道它們是如何被使用的,但我的第一個想法是它要抽象出「背景」。無論如何,我可以看到我能否找到我之前找到的內容併發布鏈接。它可能是有用的。 – wageoghe 2010-12-14 19:58:05

回答

0

我不知道使用CallContext在這裏是正確的舉措,如果願望只是提供線程安全訪問您的屬性。如果是這樣的話,鎖定語句就是你所需要的。

但是,您必須確保您正確應用

使用CallContext,您將獲得線程安全訪問,因爲當調用進入不同線程(或不同的存儲)時,您將擁有不同的CallContext實例。但是,這與訪問資源線程安全性非常不同。

如果你想跨多個線程共享相同的值,那麼鎖定語句就是要走的路。否則,如果您希望以每個線程/調用爲基礎指定特定值,請使用CallContext,或者在Thread類或ThreadStatic屬性(或任意數量的基於線程的存儲機制)上使用靜態GetData/SetData方法。

+0

我不關心同步。就像你說的,他們有許多基於上下文的存儲機制,有些在某些情況下不起作用(即ASP.NET中的CallContext和ThreadStatic),因此我的問題。 – jsw 2009-04-09 21:03:41

2

這裏是(至少部分)NHibernate的「背景」實現鏈接:

https://nhibernate.svn.sourceforge.net/svnroot/nhibernate/trunk/nhibernate/src/NHibernate/Context/

這是我不清楚究竟在何處或如何發揮作用NHibernate的背景下。也就是說,如果我想在「上下文」中存儲一些值,我會從NHibernate中獲得「上下文」並添加我的值?我不使用NHibernate,所以我不知道。

我想你可以自己看看並確定這種實現對你是否有用。顯然這個想法是注入所需的實現,這取決於應用程序的類型(ASP.NET,WCF等)。這可能意味着一些配置(如果使用MEF加載「ICurrentSessionContext」接口,則可能最小)。

無論如何,我發現這個有趣的想法時,我發現它前一段時間,而搜索信息上CallContext.SetData/GetData/LogicalSetData/LogicalGetDataThread.SetData/GetData[ThreadStatic]

此外,根據您所使用的CallContext.LogicalSetData而非CallContext.SetData,我假設您要利用與邏輯線程相關的信息將傳播到子線程的事實,而不是僅僅希望「線程安全」的地方存儲信息。因此,如果您要在應用程序啓動時設置(pr推送)AmbientActivity,然後不再推送更多活動,則任何後續線程也將成爲同一活動的一部分,因爲通過LogicalSetData存儲的數據由子線程繼承。

如果您在第一次詢問這個問題之前已經學會了什麼,我會非常感興趣的聽到它。即使你沒有,我也會有興趣瞭解你在上下文中做了什麼。目前,我正在維護一些用於記錄/跟蹤的上下文信息(類似於Trace.CorrelationManager.ActivityId和Trace.CorrelationManager.LogicalOpertionStack和log4net/NLog上下文支持)。我想保存一些上下文(當前應用程序,當前應用程序實例,當前活動(可能嵌套)),以便在應用程序或WCF服務中使用,並且我想跨WCF服務邊界「自動」傳播它。這是爲了允許記錄在中央存儲庫中的日誌語句通過客戶端/活動/等進行關聯。我們將能夠通過特定應用程序的特定實例查詢和關聯所有日誌記錄。日誌語句可能已在客戶端或一個或多個WCF服務中生成。

ActivityId的WCF傳播對我們來說不一定足夠,因爲我們想傳播(或者我們認爲我們做的)不僅僅是ActivityId。此外,我們希望將此信息從Silverlight客戶端傳播到WCF服務,並且Trace.CorrelationManager在Silverlight中不可用(至少不在4.0中,可能類似將來可用)。

當前我正在使用IClientMessageInspector和IDispatchMessageInspector對我們的「上下文」信息的傳播進行原型設計。它看起來可能會爲我們工作。

關於對System.Web的依賴關係,NHibernate實現確實有一個「ReflectiveHttpContext」,它使用反射來訪問HttpContext,因此System.Web上不存在項目依賴關係。顯然,如果HttpContext被配置爲使用,System.Web必須可用於部署應用程序的位置。