In Simple Injector why is it an error for a singleton or scoped service to depend on a transient service
我用的是简易注射器3.0.4
我有一个服务,它的生活方式是范围依赖于一个服务,它的生活方式是短暂的。
当我调用container.verify()时,会得到一个关于生活方式不匹配的诊断错误。
引起问题的临时服务被注入到其他临时服务中,所以在我继续进行并使整个项目范围达到我需要问的范围之前。为什么从一种生活方式的范围依赖于暂时的问题?瞬变每次被注入时都是新鲜的,所以没有其他东西能干扰它。从本质上讲,瞬时对象的生命周期由其注入的服务控制。
另外,我已经从这里阅读了有关这个主题的文档,我确实理解了为什么您不希望单例依赖于一个作用域服务,但是对瞬时的依赖总是安全的?
Transients are newed up fresh each time they are injected so nothing else can interfere with it.
每次从容器中请求瞬变时,都会更新它们,但是一旦它们被注入到组件中,它们就会在组件寿命内一直存在。因此,如果消费组件是一个单例组件,这意味着它将拖动所有依赖项,使它们实际上也是单例组件。当您查看通常如何实现依赖项注入时,这种行为会变得明显:
1 2 3 4 5 6 7 8 9 10 | public class SomeComponent { private readonly ILogger logger; private readonly IService service; public SomeComponent(ILogger logger, IService service) { this.logger = logger; this.service = service; } } |
如您所见,依赖项存储在组件的私有字段中,只要
In essence the lifetime of a transient object is governed by the service it is injected into.
准确地说,一个组件的生活方式至少和它的消费者一样长。然而,依赖关系可以有多个具有不同生活方式的消费者,这使得很难了解依赖关系的寿命。当注入到使用者1中时,它可能在请求的持续时间内存在,而注入到使用者2中的该依赖项的另一个实例将与应用程序的持续时间相同。
与作用域实例一样,临时注册通常不是线程安全的;否则,您将把它们注册为singleton。将瞬变保持较长时间,显然会导致并发错误或与陈旧数据相关的错误。这就是为什么简单注入器默认情况下不允许这样做并抛出异常的原因。
与简单的注入器相比,autopac如何定义其生活方式可能会让您困惑。自动空调不包含短暂的生活方式。相反,它有一种
简单注入器不允许将瞬变注入作用域实例的原因是,作用域实例也可以存活很长时间(取决于应用程序),并且不能总是假设瞬变可以安全地注入作用域使用者。
最后,这一切都是为了传达代码的意图。如果一个组件是无状态的或线程安全的,您应该将它注册为singleton。它不是线程安全的,您将它注册为作用域或瞬时的。这使任何阅读配置的人都能清楚地了解他应该如何处理这些组件,并且它允许简单的注入器为您检测任何错误配置。
虽然简单的注入器为您检测错误配置,但我得出的结论是,当您的系统是围绕纯粹由单例组件组成的对象图设计时,DI配置可以大大简化。我在这里表达了这些想法。这将消除我们在处理依赖注入时面临的许多复杂性,甚至比DI本身更快速地暴露出固体原则的违反。
before I go ahead and make my whole project scoped
这是我不建议做的事。您通常会看到,只有应用程序中的一些"叶组件"具有范围(如