1

使用 ServiceStack 我一直在解决自托管 Web 应用程序中对象生命周期管理的问题。

我的要求:

  1. 需要每个请求对象的生命周期范围。
  2. 我正在使用 Castle Windsor IoC 和实现的 ServiceStack IoC 适配器。
  3. 我的应用程序使用基类 AppHostHttpListenerPoolBase (ServiceStack v4) 自托管
  4. 可能有一天我想在 IIS 上移动,因此它必须是灵活的。

一般问题:

Castle Windsor 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 解决了这个问题,也很有趣。

4

1 回答 1

3

Funq 确实处理RequestScoped 依赖项,它将请求上下文依赖项存储在RequestContext.Instance.Items[]字典中。

任何可以注册的一次性物品都会在RequestContext.Instance.TrackDisposable()请求结束时自动处理。

在每个请求结束时,都会AppHost.OnEndRequest()触发并释放存储在该请求的 RequestContext 中的任何依赖项。

如果您的 Windsor ContainerAdapter 实现了IRelease接口,它会自动调用以释放任何可以自行处理的实例。AppHost如果您想更改默认行为,这两个 API 都可以在您的系统中覆盖:

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*/ }
}
于 2014-10-05T17:23:21.657 回答