Autofac生命周期和匹配生命周期范围内的默认提供者

时间:2011-12-28 17:06:03

标签: c# autofac

我有一个使用Autofac进行依赖注入的ASP.NET MVC Web应用程序。有时,此Web应用程序将启动一个线程,以便与请求线程分开执行某些工作。当后台线程启动时,它会从根容器建立一个新的Autofac生存期范围并运行一些操作。

public IAsyncResult Run<T>(Action<T> action)
{
    var NewTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
        using (var Scope = Runtime.Container.BeginLifetimeScope())
        {
            var Input = Scope.Resolve<T>();
            action(Input);
        }
    });

    return NewTask;
}

我在Autofac中注册的一个依赖项有两个不同的实现:一个适用于http请求生存期,另一个适用于所有其他生命周期。我试着将它们注册如下:

builder
.Register(c => new Foo())
.As<IFoo>()
.InstancePerLifetimeScope();

builder
.Register(c => new FooForHttp(HttpContext.Current))
.As<IFoo>()
.InstancePerMatchingLifetimeScope(WebLifetime.Request);

Autofac为http请求选择FooForHttp(按预期方式)。但是,当我的后台线程旋转时,任何解决IFoo的尝试都会导致异常:

  

范围内不会显示带有匹配'httpRequest'的标记的范围   在其中请求实例。这通常表明a   按HTTP请求注册的组件正在被a重新请求   SingleInstance()组件(或类似场景。)在Web下   集成始终请求来自的依赖项   DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime,   从来没有从容器本身。

我知道Autofac始终使用最后注册的提供程序作为特定组件的默认提供程序。我在这里假设它将使用最后注册的合适的提供程序。

我是否遗漏了某些内容,或者是否有更好的方法根据当前生命周期范围的标记选择提供商?

2 个答案:

答案 0 :(得分:7)

正常注册网络Foo,但不注册其他Foo。在为异步任务创建生命周期范围时,请使用在ContainerBuilder上执行操作的BeginLifetimeScope()重载。在此操作中注册背景Foo(b =&gt; b.Register()),这应该覆盖网络。 (小键盘对不起:))

答案 1 :(得分:0)

这也可以通过使用标记的生命周期范围来解决。 注册您的fisrt Foo作为标记范围的实例:

builder.RegisterType<Foo>().As<IFoo>.InstancePerMatchingLifetimeScope("YourScopeTag");

使用您注册依赖项的相同标记创建范围:

  using (var Scope = Runtime.Container.BeginLifetimeScope("YourScopeTag"))
        {
            var Input = Scope.Resolve<T>();
            action(Input);
        }

没有测试过,但应该可以正常使用

http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-matching-lifetime-scope

相关问题