【问题标题】:.Net core DI Scope validation , scoped vs transient?.Net 核心 DI 范围验证,范围与瞬态?
【发布时间】:2019-08-23 05:51:51
【问题描述】:

阅读docs

当应用在开发环境中运行时,默认 服务提供商执行检查以验证:

  • 范围服务不是直接或间接从根服务提供者解析的。
  • 作用域服务不会直接或间接注入到单例中

这意味着我不应该将 Scoped 服务注入到单例服务中。

基于瞬态服务每次被请求时都会创建一个实例的事实,VS 范围服务在整个请求的生命周期中都是单个实例:

问题:

为什么 DI 只验证作用域服务而不验证瞬态服务?

【问题讨论】:

  • 为什么需要验证瞬态。只要单例存在,瞬态实例就可以存在。瞬态实例不会注入其他任何地方,它只存在于单例实例中。
  • Fabio 我仍然不明白为什么瞬态与作用域的不同。你能提供一个有问题的例子吗?

标签: dependency-injection .net-core


【解决方案1】:

从单例解析作用域服务是很危险的。可能会导致服务在处理后续请求时状态不正确。

来自Docs 上面描述了他们为什么要进行此检查。为了更好地理解这一点,我开始阅读不同的生命周期,更多的是作为一个 autofac 人,以了解注册的 .net 核心风格。

  • 范围注册需要一个服务生命周期是一个 每个请求的实例(连接)
  • Singleton 仅在注册时或构造函数运行时定义了一个状态。 (在startup.cs
  • 瞬态是每个构造函数注入的新实例,即每个 依赖。

通常,您会使用单例模式在内存中维护应用程序生命周期中的某种状态等,有很多用例,但重要的是要了解单例类的构造函数(注入依赖项的位置)将在您的整个应用程序生命周期中运行一次且仅一次

您可以想象,在考虑到上述情况的同时将作用域或瞬态服务注入单例会导致一些......意想不到的结果,您希望您的服务能够遵守其特定的生命周期,但实际上它真的只是由于单例的性质,每次都是相同的实例。

根据我的理解回答您的问题:注入单例的瞬态(虽然本质上不正确)仍然可以正常工作,因为它的生命周期很短并且几乎没有破坏状态的风险,而作用域保证单个请求的生命周期(以某种请求缓存为例),作用域无法在注入单例时遵守该生命周期。

【讨论】:

  • 怎么回事? Singleton 的构造函数只运行一次。如果我注入一个临时服务,那么它将永远不会被释放
  • 我已经知道了。问题仍然存在。为什么注入作用域与注入瞬态不同。为什么验证只是 (!!) For scoped.
  • 好的,我快到了。瞬态变为单例。是的。但是为什么 scoped 也不会变成单例呢?除了给定的事实。认为 scoped 也将提升为 singleton 是合乎逻辑的。所以我想唯一的问题是为什么范围没有提升。 ?
  • 假设您有一个作用域服务,它为进入您的应用程序的 Web 请求存储 GameId(int) - GameService.cs,在您的应用程序中的某个时刻,GameId 会发生变化,因为用户未成年,不允许玩该游戏并重定向到另一个新游戏 - 您同意 GameService 中的 GameId 属性更改?如果你将 GameService 注入到单例中gameid 将永远不会改变。 Microsoft 希望通过验证这一点来保护您免受这些错误的影响。临时服务不存储状态 - 因此您没有问题。
  • 这里的圣杯是最后一句话。瞬态不应该存储状态。我错过了那个信息。现在一切都说得通了。所以瞬态不存储状态,如果升高会变成单例,这可能导致内存泄漏。只是因为范围服务存储/可以存储状态,它们会警告我们不要提升。对吗?
猜你喜欢
  • 2021-09-05
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
  • 2020-11-06
  • 2021-02-27
  • 1970-01-01
  • 2022-06-28
  • 1970-01-01
相关资源
最近更新 更多