71

两个范围有什么区别?

Module在每一层(存储库、服务、MVC 应用程序)中构建(s),但是为了让InstancePerHttpRequest你需要 Autofac.Mvc 程序集。

我应该在我的存储库和服务层中使用哪个范围?

4

3 回答 3

128

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

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

唯一真正的区别在于,如果您注册了一项服务,InstancePerHttpRequest并且您从另一项注册为SingleInstance. 在这种情况下:

  • SingleInstance组件位于根范围
  • InstancePerHttpRequest组件位于名为“AutofacWebRequest”的范围内,它是根范围的子范围

Autofac 不允许从子范围解析 - 所以本质上,SingleInstance服务找不到InstancePerHttpRequest服务。

但是,如果在这种情况下您使用InstancePerLifetimeScope(而不是InstancePerHttpRequest),那么您的服务将很好地解决。

我写了一篇相当详尽的文章,其中包含可下载的代码,试图详细解释所有这些 -请参阅此处。引用文章:

这里一个常见的误解是,在 WebAPI 应用程序中使用 InstancePerLifetimeScope 注册组件意味着您的组件位于 Web 请求的范围内——即“生命周期”是指“Web 请求的生命周期”。正如你在这里看到的,这是错误的。

组件的生命周期由解析它的范围决定。

由于 SingletonResolvable 从根范围解析其令牌,因此该令牌实例位于根范围内,而不是 Web 请求的范围内。我之前说过,但我再说一遍:这个令牌将一直存在,直到整个应用程序被处理掉(例如,IIS 工作进程被回收)。任何从根范围请求 ScopeToken 的东西都将被引用到该令牌。

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

于 2014-04-29T05:17:08.430 回答
7

应用程序中唯一能够完全决定对象生命周期的地方是组合根。

在这种情况下,您会遇到冲突——您有一个通用模块,它不应该访问 MVC 集成提供的扩展方法——但您需要访问它才能正确管理生命周期。在这种情况下,如果您的模块可以提供合理的默认值,例如InstancePerLifetimeScope,那么这就是我在模块级别所做的。然后,您让组合根覆盖该行为。在这种情况下,组合根会将生命周期更改为InstancePerHttpRequest. 由于最后一次注册将覆盖之前的注册,因此您应该处于良好状态。

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

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

相反(在足够大的项目中),我在组合根级别创建模块,因为在这个级别我清楚地知道它们应该如何连接在一起。有时我会创建一个Ioc包含模块并充当默认组合根的程序集——但这通常在“真正的”组合根(例如,拉入程序集的控制台或 MVC 应用程序Ioc)处被覆盖。

于 2012-08-26T04:57:43.850 回答
2

在 Autofac 中,每个生命周期范围是使用嵌套生命周期创建自定义范围的通用方法。

UsingInstancePerLifetimeScope为您提供每个请求范围,这增加了单个请求的组件生命周期和InstancePerLifetimeScrope该组件的内部使用。

在您需要的任何地方使用InstancePerLifetimeScope,或者如果Autofac.Integration.Mvc在您的服务层中引用程序集是一个问题 - 在请求和使用的每个开始处手动创建嵌套范围InstancePerLifetimeScope

于 2012-08-26T01:38:00.477 回答