我有一个使用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
的操作都会导致异常:
我知道Autofac总是使用最后注册的提供程序作为特定组件的默认提供程序。我在这里做了一个假设,即它将使用最后注册的合适的提供程序。在请求实例的作用域中,没有与“httpRequest”匹配的标记范围可见。这通常表示正在请求一个按HTTP请求注册的组件,但该组件是由SingleInstance()组件(或类似情况)请求的。在Web集成下,请始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖项,而不是从容器本身请求。
我是否遗漏了什么,或者有没有更好的方法基于当前生命周期范围的标记选择提供程序?
BeginLifetimeScope
的重载,而那正是我所需要的! - Michael PetitoAutofac.Integration.Web.ContainerProvider
有一个类似的构造函数重载,它接受相同的操作。我决定从那一端提供覆盖,因为覆盖是特定于 Web 请求的。 - Michael Petito