Autofac-InstancePerHttpRequest 对 InstancePerLifetimeScope

这两个范围有什么不同?

我在每一层(仓库,服务,MVC 应用程序)构建 Module(s) ,但是为了有 InstancePerHttpRequest你需要自动工厂。Mvc 装配。

在存储库和服务层中应该使用哪个作用域?

37643 次浏览

在 Autofac 每一生作用域中,使用嵌套生存期创建自定义作用域是一种通用方法。

使用 InstancePerLifetimeScope为您提供 每项要求作用域,它为单个请求增加组件生存期,并在内部为此组件使用 InstancePerLifetimeScrope

在任何需要的地方使用 InstancePerLifetimeScope,或者如果在服务层中有对 Autofac.Integration.Mvc组件的引用是一个问题-在每次请求开始时手动创建嵌套作用域,并使用 InstancePerLifetimeScope

应用程序中完全能够决定对象生存期的唯一位置是组合根。

在这种情况下,您有一个冲突——您有一个通用模块,它不应该访问 MVC 集成提供的扩展方法——但是您需要访问它,以便正确地管理生命周期。在这种情况下,如果您的模块可以提供合理的默认值,比如 InstancePerLifetimeScope,那么这就是我在模块级别要做的事情。然后,让复合根覆盖该行为。在这种情况下,组合根将把生存期改为 InstancePerHttpRequest。由于最后一次注册会覆盖较早的注册,你应该是在良好的状态。

我实际上已经不再创建与包含给定层的程序集共存的模块了,原因有几个:

  1. 它引入了对 Autofac 的依赖关系,除了在我的组合根目录中,我不想要这种依赖关系
  2. 它表明模块知道应该如何管理它的生存期,这通常是不正确的。如果是这样,为什么不提供提供生命周期管理的工厂或其他类呢?

相反(在足够大的项目中) ,我在组合根级别创建模块,就像在这个级别我已经讨论过它们应该如何连接在一起的外显知识。有时我会创建一个包含模块的 Ioc程序集,它充当默认的组合根目录——但是这通常在“真正的”组合根目录中被覆盖(例如,拉入 Ioc程序集的控制台或 MVC 应用程序)。

InstancePerHttpRequestInstancePerApiRequest基本上做同样的事情——你为每个离散的 web 请求获得一个单独的服务实例。其余的答案我将使用 InstancePerHttpRequest,但是请记住,这两个是可以互换的。

InstancePerLifetimeScope意味着将为请求您的服务的每个生命周期范围创建一个新的服务实例。每个 Web 请求都有自己的生命周期范围,因此在实践中,这两个请求通常会做完全相同的事情。

唯一真正的区别在于,如果您有一个注册在 InstancePerHttpRequest下的服务,并且您从另一个注册为 SingleInstance的服务请求其中一个服务。在这种情况下:

  • SingleInstance组件位于 范围内
  • InstancePerHttpRequest组件位于名为“ AutofacWebRequest”的作用域中,该作用域是根作用域的 孩子

Autofac 不允许从子作用域进行解析-因此本质上,SingleInstance服务无法找到 InstancePerHttpRequest服务。

但是,如果在这个场景中您使用了 InstancePerLifetimeScope(而不是 InstancePerHttpRequest) ,那么您的服务就可以很好地解析。

我已经写了一篇相当详尽的文章,试图用可下载的代码来详细解释这一切—— 看这里。引用文章中的话:

一个常见的误解是,在 WebAPI 应用程序中使用 InstancePerLifetimeScope 注册您的组件意味着您的组件位于 Web 请求的范围内——也就是说,“ Lifetime”指的是“ Web 请求的 Lifetime”。如你所见,这是错误的。

组件的生存期由解析它的作用域决定。

由于 SingletonResolable 从根作用域解析其令牌,因此令牌实例位于根作用域,而不是 Web 请求的作用域。我之前已经说过了,但是我还要再说一遍: 这个令牌将一直存在,直到整个应用程序被处理掉(例如,IIS 辅助进程被回收)。从根作用域请求 ScopeToken 的任何内容都将被给予对该令牌的引用。

希望这有所帮助-我欣赏这个问题现在相当老,但它仍然非常相关!