如何使用Autofac来解析Nancy创建的子生命周期范围中的类型的每个请求依赖项的实例

时间:2015-02-17 10:34:44

标签: c# dependency-injection autofac nancy

我们在Windows服务中托管了多个应用程序,这些应用程序自托管Nancy端点,以便公开有关应用程序操作的检测。

我们使用Autofac作为我们的IOC。在所有应用程序共享的核心DLL中,将几个存储库注册到根容器中;然后使用派生自Nancy.Autofac.Bootstrapper的引导程序将此容器作为其容器传递给Nancy。

我们发现,当Nancy收到Web请求时,它会从根容器中解析对存储库的请求,这会导致内存被非垃圾收集IDisposable消耗,因为根容器会不要超出范围(它具有Windows服务的生命周期)。这导致了服务"泄漏"存储器中。

然后我们切换到一个模型,我们在Nancy bootstrapper中使用InstancePerRequest方法使用ConfigureRequestContainer()添加了存储库的注册:

protected override void ConfigureRequestContainer(ILifetimeScope container, NancyContext context)
{
    base.ConfigureRequestContainer(container, context);
    PerRequestContainerBuilder().Update(container.ComponentRegistry);
}

private static ContainerBuilder PerRequestContainerBuilder()
{
    var builder = new ContainerBuilder();

    // Dependency for repository
    builder.RegisterType<SystemDateTimeProvider>().InstancePerRequest().As<IDateTimeProvider>();

    // Repository
    builder.RegisterType<BookmarkRepository>().InstancePerRequest().As<IBookmarkRepository>();

    return builder;
}

我们还覆盖了CreateRequestContainer()方法,以使用标记MatchingScopeLifetimeTags.RequestLifetimeScopeTag创建请求容器。

protected override ILifetimeScope CreateRequestContainer(NancyContext context)
{
     return ApplicationContainer.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag);
}

这似乎已经解决了IDisposable未被处理的问题 - 子请求容器被放置在Web请求管道的末尾,并且由它解析的对象也被处理并最终被垃圾收集。

我们的问题是,这似乎是将存储库的实现细节泄漏到服务中,因为我们不仅要在ConfigureRequestContainer()中注册存储库,还要注册存储库所需的任何其他对象,即如果我们需要为了改变存储库的实现,我们必须遵循依赖链#34;使用它在每个服务中注册所需的对象 - 这似乎是错误的。

我们是否有办法让Autofac从根容器中解析存储库的支持对象,但是将注册信息保留在Web请求容器的范围内?或者有没有办法在创建根容器时自动将现有注册从子容器复制到子容器中?

1 个答案:

答案 0 :(得分:6)

Autofac应自动解析“父”生命周期中的实例。如果使用InstancePerRequest配置注册,Autofac将使用特殊的生命周期标记MatchingScopeLifetimeTags.RequestLifetimeScopeTag注册这些服务,以便以后可以在正确的范围内解析。

这意味着不需要使用Nancy bootstrapper的ConfigureRequestContainer方法来执行请求范围的注册。你已经做到了!只要Nancy使用InstancePerRequest中使用的相同标记(从Nancy 1.1开始为done by default)创建请求生命周期,就应该正确解析服务。

示例:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var builder = new ContainerBuilder();

        // Do request-scoped registrations using InstancePerRequest...

        var container = builder.Build();

        // Pass the pre-built container to the bootstrapper
        var bootstrapper = new MyAwesomeNancyBootstrapper(container);

        app.UseNancy(options => options.Bootstrapper = bootstrapper);
    }
}
public class MyAwesomeNancyBootstrapper : AutofacNancyBootstrapper
{
    private readonly ILifetimeScope _lifetimeScope;

    public MyAwesomeNancyBootstrapper(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
    }

    protected override ILifetimeScope GetApplicationContainer()
    {
        return _lifetimeScope; // Tell Nancy you've got a container ready to go ;)
    }
}

此设置应该足够(从Nancy 1.1开始。在早期版本中,您还必须覆盖CreateRequestContainer方法并在创建请求生存期范围时传递请求生命周期标记。)

编辑:我在https://github.com/khellang/Nancy.AutofacExample

为您准备了一个示例