Autofac – InstancePerHttpRequest与InstancePerLifetimeScope

两个范围有什么区别?

我在每个层(存储库,服务,MVC应用程序)build立Module (s),但为了有InstancePerHttpRequest您需要Autofac.Mvc程序集。

我应该在我的Repository和Service层中使用哪个范围?

InstancePerHttpRequestInstancePerApiRequest本质上是做同样的事情 – 您为每个离散的Web请求获得您的服务的单个实例。 我将使用InstancePerHttpRequest作为答案的其余部分,但请记住,这两个是可以互换的。

InstancePerLifetimeScope意味着服务的一个新的实例将被创build为每个生命周期范围要求你的服务。 每个Web请求都有自己的新鲜的生命周期范围,所以在实践中,这两者往往会做同样的事情。

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

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

Autofac不允许从子范围解决 – 实质上, SingleInstance服务找不到InstancePerHttpRequest服务。

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

我已经写了一个相当详尽的文章与可下载的代码,试图详细解释这一切 – 见这里 。 引用文章:

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

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

由于SingletonResolvable从根作用域parsing其标记,因此该标记实例位于根作用域中,而不是Web请求的作用域。 我之前已经说过了,但我会再说一遍:这个标记将一直存在,直到整个应用程序被处置掉(例如,IIS工作进程被回收)。 从根作用域向ScopeToken请求的任何内容都将被赋予对该令牌的引用。

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

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

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

实际上,我已经开始创build与包含给定图层的程序集共存的模块,原因如下:

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

相反(并且在足够大的项目中),我在组成层级创build模块,因为在这个级别上,我明确知道它们应该如何连接在一起。 有时候我会创build一个包含模块的Ioc程序集,它作为一个默认的合成根,但是在“真实的”合成根(例如Ioc程序集的控制台或MVC应用程序)中通常会覆盖它。

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

使用InstancePerLifetimeScope每个请求范围提供了一个请求范围,该范围为单个请求添加了组件生存期,并在内部为此组件使用了InstancePerLifetimeScrope

在需要的地方使用InstancePerLifetimeScope ,或者在服务层中引用Autofac.Integration.Mvc程序集时出现问题 – 在请求的每个开始处手动创build嵌套的作用域,并使用InstancePerLifetimeScope