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

相关问题