1

使用ServiceStack我堅持自我託管的Web應用程序中的對象生命週期管理問題。ServiceStack自己託管的應用程序與每個請求生命週期範圍

我的要求:

  1. 需要每個請求的對象生命週期範圍。
  2. 我正在使用Castle Windsor IoC和已實施的ServiceStack IoC適配器。
  3. 我的應用程序是自託管的,具有基類AppHostHttpListenerPoolBase(ServiceStack v4)
  4. 可能有一天我想在IIS上移動,因此它必須是靈活的。

普遍的問題:

溫莎城堡的IoC實現了自己的每個請求的生命週期策略,但它被綁定到HTTP模塊,因此它只能與IIS託管應用程序。因此,我必須實現我的自定義IScopeAccessor(由Castle Windsor提供)來處理對象的生命週期。這裏的問題是沒有可以綁定到當前請求的鉤子。

鑑於

public class MyScopeAccessor : IScopeAccessor 
{ 
    public ILifetimeScope GetScope(CreationContext context) 
    { 
     //implement it 
    } 
} 

我要實現GetScope方法。

主要有兩種觀點我無法完成:

使用的[Threadstatic]

在MyScopeAccessor我只是存儲

[ThreadStatic] 
private static ILifetimeScope _currentLifetimeScope; 

,並創建第一個GetScope後新的範圍,如果它不是初始化呢。

問題:

  1. 很難處理。處理_currentLifetimeScope的最佳方式是實現自定義的IServiceRunner(或從ServiceRunner繼承),覆蓋AfterEachRequest方法。但我不完全知道AfterEachRequest是否在請求線程中實際執行。
  2. 移動到IIS可能會導致一些問題,因爲據我所知IIS並不能保證在不同的請求上下文之間的綁定。

使用IRequest實例

在MyScopeAccessor我只是存儲

private static readonly ConcurrentDictionary<IRequest, ILifetimeScope> LifetimeScopes; 

,並創建和相應的定製ServiceRunner方法(OnBeforeEachRequest,OnAfterEachRequest)處理當前生存範圍。

問題:

  1. 我不知道如何從GetScope獲得全球訪問當前請求,MyScopeAccessor一無所知服務和請求。

另外,如果ServiceStack默認Funq IoC解決了這個問題,這很有趣。

回答

3

Funq確實處理RequestScoped dependencies,它在RequestContext.Instance.Items[]字典中存儲請求上下文依賴關係。

任何一次性用品都可以在​​中註冊,在請求結束時自動處理。

在每次請求結束時,會觸發AppHost.OnEndRequest(),它會通過並釋放存儲在該請求的RequestContext中的任何依賴項。

如果您的Windsor ContainerAdapter實現了IRelease接口,它會自動調用以釋放任何可以自己處理的實例。如果要更改默認行爲,則這兩個API都可覆蓋AppHost

public virtual void OnEndRequest() 
{ 
    var disposables = RequestContext.Instance.Items.Values; 
    foreach (var item in disposables) 
    { 
     Release(item); 
    } 

    RequestContext.Instance.EndRequest(); 
} 

public virtual void Release(object instance) 
{ 
    try 
    { 
     var iocAdapterReleases = Container.Adapter as IRelease; 
     if (iocAdapterReleases != null) 
     { 
      iocAdapterReleases.Release(instance); 
     } 
     else 
     { 
      var disposable = instance as IDisposable; 
      if (disposable != null) 
       disposable.Dispose(); 
     } 
    } 
    catch { /*ignore*/ } 
} 
+0

謝謝。現在很清楚Funq是如何工作的。但主要問題是如何從任意代碼位置(包括MyScopeAccessor)「映射」到當前請求上下文。有了這個能力,我可以做任何事情,也可以處置。另外,我不想實施已經實施的Castle Windsor的一部分。 RequestContext.Instance.Items是請求上下文標識的最佳選擇嗎?這就像使用靜態ConcurrentDictionary LifetimeScopes;'一樣使用RequestContext.Instance.Items對象作爲關鍵字。 – 2014-10-05 18:10:00

+0

並沒有'RequestContext.Instance'適合,因爲它似乎是一個單身? – 2014-10-05 18:11:47

+1

@ ValentinP.'RequestContext.Instance'是一個單例,您可以使用'RequestContext.Instance.Items'對象字典來保存請求作用域的依賴關係來標識請求。在幕後,Item默認使用'HttpContext.Current.Items'(ASP.NET)或'CallContext.LogicalData'作爲自託管,否則'RequestContext.RequestItems'如果'RequestContext.UseThreadStatic = true'。有關詳細信息,請參閱[RequestContext](https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/RequestContext.cs)impl。 – mythz 2014-10-05 18:23:30

相關問題