Autofac - InstancePerHttpRequest与InstancePerLifetimeScope

时间:2012-08-26 01:29:07

标签: c# asp.net-mvc-3 dependency-injection autofac

两个范围之间有什么区别?

我正在每层构建Module(存储库,服务,MVC应用程序),但为了拥有InstancePerHttpRequest,您需要Autofac.Mvc程序集。

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

3 个答案:

答案 0 :(得分:100)

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

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

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

  • SingleInstance组件位于 root 范围
  • InstancePerHttpRequest组件位于名为" AutofacWebRequest"的范围内,该范围是根范围的

Autofac不允许从子范围解析 - 实际上SingleInstance服务无法找到InstancePerHttpRequest服务。

但是,如果在这种情况下您使用了InstancePerLifetimeScope(而非InstancePerHttpRequest),那么您的服务就可以解决。

我已经写了一篇包含可下载代码的相当详尽的文章,试图详细解释所有这些 - see here。引用文章:

  

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

     

组件的生命周期取决于解决方案的范围。

     

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

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

答案 1 :(得分:8)

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

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

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

  1. 它引入了对Autofac的依赖,除了我的作品根
  2. 之外我不想要它
  3. 它表明模块知道如何管理它的生命周期,这通常不正确。如果确实如此,为什么不提供提供终身管理的工厂或其他类?
  4. 相反(并且在大到足以保证的项目中),我在组合根级别创建模块,因为在这个级别我明确知道它们应该如何连接在一起。有时我会创建一个包含模块的Ioc程序集,它充当默认的组合根 - 但这通常会在“真正的”组合根(例如,拉入控制台的控制台或MVC应用程序)中被覆盖。 Ioc汇编)。

答案 2 :(得分:2)

在Autofac per lifetime 范围是使用嵌套生命周期创建自定义范围的一般方法。

使用InstancePerLifetimeScope为您提供每个请求范围,这会为单个请求添加组件生命周期,并在内部对此组件使用InstancePerLifetimeScrope

在您需要的任何地方使用InstancePerLifetimeScope,或者如果在服务层中引用Autofac.Integration.Mvc程序集是个问题 - 在每个请求开始时手动创建嵌套作用域并使用{{1 }}