在用作ServiceStack的IoC时,在autofac中配置生存期范围

时间:2013-02-12 15:03:44

标签: scope httprequest servicestack autofac

我目前正在使用AutoFac作为ServiceStack Web服务应用的DI容器。我能够配置接线和所有内容,但在阅读了Scopes部分之后,我很遗憾在注册我的组件时最好使用哪个范围。在我们的特定情况下,我认为PerHttpRequest范围可以正常(如果我错了请纠正我)我希望在请求结束后立即处理依赖关系。

我的问题是,如何在容器中设置它?我似乎无法在autofac中包含的方法中找到“PerHttpRequest”生命周期范围。我也不确定ServiceStack是否会在幕后为我做这种自动化。

我在.Net 4上的ServiceStack 3.9.35上使用Autofac 3.0.1(作为常规ASP主机运行,而不是MVC)。我也使用了here描述的类作为IContainer适配器。

4 个答案:

答案 0 :(得分:5)

我想避免依赖MVC的开销,所以第一个答案对我来说并不适用。

相反,我使用Funq来注册PerRequest ILifetimeScope,并在解析依赖关系之前解析ConatinerAdaptor中的ILifetimeScope。

public class AutofacLifetimeScopeIocAdapter : IContainerAdapter
{
    private readonly Container _requestContainer;

    public AutofacLifetimeScopeIocAdapter(Funq.Container requestContainer)
    {
        _requestContainer = requestContainer;
    }


    public T Resolve<T>()
    {
        var currentContainer = _requestContainer.Resolve<ILifetimeScope>();

        return currentContainer.Resolve<T>();
    }

    public T TryResolve<T>()
    {
        var currentContainer = _requestContainer.Resolve<ILifetimeScope>();

        T result;

        if (currentContainer.TryResolve<T>(out result))
        {
            return result;
        }

        return default(T);
    }

}

然后用这个

初始化
_autofacContainerRoot = builder.Build();
        IContainerAdapter adapter = new AutofacLifetimeScopeIocAdapter(container);

        container.Register<ILifetimeScope>((c) => _autofacContainerRoot.BeginLifetimeScope())
            .ReusedWithin(ReuseScope.Request);

        container.Adapter = adapter;

然后用

进行清理
public override void OnEndRequest()
    {
        var currentContainer = _container.Resolve<ILifetimeScope>();
        currentContainer.Dispose();

        base.OnEndRequest();
    } 

这似乎与Autofac - SingleInstance,InstancePerDependency和现在的InstancePerLifetimeScope(perRequest)一样。

HostContext.Instance.Items集合上的Mythz响应很可能用于删除

的需要
var currentContainer = _container.Resolve<ILifetimeScope>();

分辨率,这应该可以提高性能。

答案 1 :(得分:4)

我想我已经弄清楚如何使这项工作(使用Autofac 2.6,我现在卡住了。)它涉及使用以下适配器和Autofac.Mvc3包:

public class AutofacIocAdapter : IContainerAdapter
{
    private readonly IContainer _autofacRootContainer;
    private readonly Container _funqContainer;

    public AutofacIocAdapter(IContainer autofacRootContainer, Container funqContainer)
    {
        // Register a RequestLifetimeScopeProvider (from Autofac.Integration.Mvc) with Funq
        var lifetimeScopeProvider = new RequestLifetimeScopeProvider(autofacRootContainer,null);
        funqContainer.Register<ILifetimeScopeProvider>(x => lifetimeScopeProvider);
        // Store the autofac application (root) container, and the funq container for later use
        _autofacRootContainer = autofacRootContainer;
        _funqContainer = funqContainer;
    }

    public T Resolve<T>()
    {           
        return ActiveScope.Resolve<T>();
    }

    public T TryResolve<T>()
    {
        T result;
        if (ActiveScope.TryResolve(out result))
        {
            return result;
        }
        return default(T);
    }

    private ILifetimeScope ActiveScope
    {
        get
        {
            // If there is an active HttpContext, retrieve the lifetime scope by resolving
            // the ILifetimeScopeProvider from Funq.  Otherwise, use the application (root) container.
            return HttpContext.Current == null
                        ? _autofacRootContainer
                        : _funqContainer.Resolve<ILifetimeScopeProvider>().GetLifetimeScope();
        }
    }
}

实施步骤:

  1. 将Autofac.Mvc3 NuGet包添加到您的Web项目中(注意:确实如此) 表明您的项目没有使用MVC。解决方案可能与Autofac 3略有不同,后者不能使用Mvc3集成。)
  2. 按住ServiceStack IoC页面连接自定义IContainerAdapter 对于Autofac,使用以下实现

答案 2 :(得分:2)

注意RequestScope in ServiceStack's IOC仅指ServiceStack的内置Funq IOC。

要在另一个IOC容器(如AutoFac)中使用RequestScope,通常需要在请求结束时通知AutoFac,以便它可以清理其所有请求范围的实例。为此,ServiceStack提供了AppHostBase.OnEndRequest()挂钩,您可以覆盖它以在每个请求结束时获取执行自定义逻辑。

我不熟悉AutoFac的自定义生命周期范围如何运作,但有关它的更多详细信息,请参阅:

在ServiceStack中管理实例可能有用的其他信息是,放入HostContext.Instance.Items字典中的每个实例或添加到HostContext.Instance.TrackDisposable的一次性实例都是automatically disposed at the end of each request

答案 3 :(得分:2)

更新2015-11-25 :我使用全局请求和响应过滤器更改了实施。我将ServiceStack V3和V4解决方案都放入了这个repository,两个版本都以nuget packages的形式提供。

我通过在Application_BeginRequest中打开一个新范围并在Application_EndRequest中处理来解决了这个问题。在容器适配器中,我检查这个范围是否存在并使用它,如果没有,我使用容器。这允许使用.InstancePerRequest()注册范围。

用gists here描述。