【发布时间】:2017-12-08 03:00:18
【问题描述】:
这两种作用域有什么区别?
我在每一层(存储库、服务、MVC 应用程序)中构建 Module(s),但为了拥有 InstancePerHttpRequest,您需要 Autofac.Mvc 程序集。
我应该在我的存储库和服务层中使用哪个范围?
【问题讨论】:
标签: c# asp.net-mvc-3 dependency-injection autofac
这两种作用域有什么区别?
我在每一层(存储库、服务、MVC 应用程序)中构建 Module(s),但为了拥有 InstancePerHttpRequest,您需要 Autofac.Mvc 程序集。
我应该在我的存储库和服务层中使用哪个范围?
【问题讨论】:
标签: c# asp.net-mvc-3 dependency-injection autofac
InstancePerHttpRequest 和InstancePerApiRequest 本质上是做同样的事情——你会为每个离散的 Web 请求获得一个服务实例。我将使用InstancePerHttpRequest 作为其余答案,但请记住,这两者是可以互换的。
InstancePerLifetimeScope 表示将为每个需要您的服务的生命周期范围创建一个新的服务实例。每个 Web 请求都有自己的新生命周期范围,因此在实践中,这两个请求通常会做完全相同的事情。
唯一真正的区别在于,如果您在InstancePerHttpRequest 下注册了一个服务,并且您从另一个注册为SingleInstance 的服务请求其中一个服务。在这种情况下:
SingleInstance 组件位于 root 范围内InstancePerHttpRequest 组件位于名为“AutofacWebRequest”的范围内,它是根范围的子
Autofac 不允许从子作用域解析 - 所以本质上,SingleInstance 服务无法找到 InstancePerHttpRequest 服务。
但是,如果在这种情况下您使用了InstancePerLifetimeScope(而不是InstancePerHttpRequest),那么您的服务将很好地解决。
我写了一篇相当详尽的文章,其中包含可下载的代码,试图详细解释这一切 - see here。引用文章:
这里的一个常见误解是,在 WebAPI 应用程序中使用 InstancePerLifetimeScope 注册您的组件意味着您的组件位于 Web 请求的范围内——即“生命周期”是指“网络请求的生命周期”。正如您在此处看到的,这是错误的。
组件的生命周期由解决它的范围决定。
由于 SingletonResolvable 从根范围解析其令牌,因此该令牌实例位于根范围内,而不是 Web 请求的范围内。我以前说过,但我再说一遍:这个令牌将一直存在,直到整个应用程序被处理掉(例如,IIS 工作进程被回收)。任何从根作用域请求 ScopeToken 的东西都将获得对该标记的引用。
希望有所帮助 - 我很感激这个问题现在已经很老了,但它仍然非常相关!
【讨论】:
InstancePerLifetimeScope 而不是 InstancePerRequest。更多信息here
InstancePerMatchingLifetimeScope 来处理这种情况,这实际上是InstancePerRequest 在幕后所做的。然后,我们使用我们的生命周期范围标签为每个作业启动一个新的生命周期范围。希望有帮助!
您的应用程序中唯一能够完全决定对象生命周期的位置是组合根。
在这种情况下,您会遇到冲突 - 您有一个通用模块,它不应该访问 MVC 集成提供的扩展方法 - 但是您需要访问它才能正确管理生命周期.在这种情况下,如果您的模块可以提供合理的默认值,例如InstancePerLifetimeScope,那么这就是我在模块级别所做的。然后,您让组合根覆盖该行为。在这种情况下,组合根会将生命周期更改为InstancePerHttpRequest。由于最后一次注册将覆盖之前的注册,因此您应该处于良好状态。
我实际上已经不再创建与包含给定层的程序集共存的模块,原因如下:
相反(在足够大的项目中),我在组合根级别创建模块,因为在这个级别我清楚地知道它们应该如何连接在一起。有时我会创建一个包含模块并充当默认组合根的Ioc 程序集——但这通常在“真正的”组合根(例如,拉入@987654324 的控制台或MVC 应用程序)处被覆盖@大会)。
【讨论】:
在 Autofac 中,每个生命周期作用域是一种使用嵌套生命周期创建自定义作用域的通用方法。
使用InstancePerLifetimeScope 为您提供每个请求 范围,它为单个请求添加组件生命周期,并在内部为此组件使用InstancePerLifetimeScrope。
在您需要的任何地方使用InstancePerLifetimeScope,或者如果在您的服务层中引用Autofac.Integration.Mvc 程序集存在问题 - 在请求的每个开头手动创建嵌套范围并使用InstancePerLifetimeScope。
【讨论】:
InstancePerLifetimeScope,在我的global.asax 中使用InstancePerHttpRequest?
BeginLifetimeScope 方法(可以作为 ILifetimeScope 注入您的类型或从 AutofacDependencyResolver.Current.RequestLifetimeScope 获取)。并在 EndRequest 事件中处理您的嵌套生命周期。