一个注册过程中可以指定多个Autofac生命周期吗?

9

我正在使用带有MVC4插件的Autofac IoC容器,该插件提供了InstancePerHttpRequest生命周期范围。然而,在我的项目中,我有Web、Web API和后台工作线程。在下面的示例中,我假设当不是来自Web请求时,InstancePerHttpRequest作用不大。

builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>()
    .InstancePerHttpRequest()

我想知道是否可能像以下示例那样,让容器选择最适合的生命周期范围?
builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>()
    .InstancePerHttpRequest()
    .InstancePerApiRequest()
    .InstancePerDependency();

在这种情况下,我的意图是如果请求来自Web请求,则选择InstancePerHttpRequest范围,如果来自WebApi请求,则选择InstancePerApiRequest范围,如果被应用程序工作线程使用,则使用InstancePerDependency范围。有什么想法,是否可能或类似的方法?谢谢。
1个回答

14

这个问题与以下内容有相当大的重叠:

你需要查看这些内容以获取一些想法。

简短回答是:这种情况不支持开箱即用。 你需要做几件事情之一。

选项:你可以为后台线程创建一个不同的容器。 这将不允许您共享应用程序级别的单例,但对于您的应用程序可能是可以接受的。

选项:您可以从容器创建两个生存期范围,并将不同的注册作为调用 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源代码以获取多租户支持的示例。

选项:您可以使用“最低公共分母”类型的注册,例如InstancePerDependencyInstancePerLifetimeScope,跳过为应用程序的不同部分设置不同生命周期的概念。

请注意,现在,在技术上,内部上,InstancePerHttpRequestInstancePerWebApiRequest之间没有区别。它们最终都归结为完全相同的事情,并且可以有效地互换使用。(我不能保证这种情况永远不会改变,但我不知道为什么需要改变)。


太棒了!感谢您的详细回复,这非常有帮助。 - chriskopec
我认为这会很有用。一个例子是在使用EF框架时,如果dbcontext web api action调用需要访问数据库的类的新线程,那么如果它只是instanceperhttprequest,很可能会抛出异常,所以需要具有InstancePerLifetimeScope的灵活性。最好几乎只使用InstancePerLifetimeScope. - koo9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接