这个问题与这些有一些相当大的重叠:
你会想看看那些想法。
简短的回答是:这种东西不支持开箱即用。您需要做几件事中的一件。
选项:您可以为后台线程使用不同的容器。这不允许您共享应用程序级别的单例,但这对您的应用程序来说可能没问题。
选项:您可以在容器外创建两个生命周期范围,并在调用BeginLifetimeScope
. 这将允许您共享应用程序级的单例,并在不同的上下文中为相同的组件具有不同的生命周期范围。不过,管理注册有点困难,而且您将需要两个不同的服务定位器(例如DependencyResolver
),因为每个逻辑上下文都需要从其自己的范围内解析。
var builder = new ContainerBuilder();
builder.RegisterType<AppLevelSingleton>().SingleInstance();
var container = builder.Build();
// Create a nested lifetime scope for your background threads
// that registers things as InstancePerDependency, etc. Pass
// that scope to whatever handles dependency resolution on the thread.
var backgroundScope = container.BeginLifetimeScope(
b => b.RegisterType<DatabaseFactory>()
.As<IDatabaseFactory>()
.InstancePerDependency());
// Create a nested lifetime scope for the web app that registers
// things as InstancePerHttpRequest, etc. Pass that scope
// as the basis for the MVC dependency resolver.
var webScope = container.BeginLifetimeScope(
b => b.RegisterType<DatabaseFactory>()
.As<IDatabaseFactory>()
.InstancePerHttpRequest());
var resolver = new AutofacDependencyResolver(webScope);
DependencyResolver.SetResolver(resolver);
如果你真的想看中这个选项,你可以实现一个自定义IContainer
,它可以检测它在哪个上下文中,并从适当的嵌套范围内解决问题。这就是多租户 Autofac 支持的工作方式。但是,这是一个更复杂的解决方案,所以我不打算在这里全部写出来。查看 Autofac 源代码以获取多租户支持的示例。
选项:您可以使用“最小公分母”类型的注册,例如InstancePerDependency
orInstancePerLifetimeScope
并跳过应用程序的不同部分具有不同生命周期的概念。
请注意,现在,从技术上讲,在内部, what和do之间没有区别InstancePerHttpRequest
InstancePerWebApiRequest
。它们都归结为完全相同的东西,并且可以有效地互换。(我不能保证它会永远这样,但我不知道为什么它需要改变。)