在Simple Injector中,为什么单例或作用域服务依赖于瞬态服务是错误的

扭曲的

我正在使用简单的注射器3.0.4

我有一项服务,其生活方式的范围取决于具有短暂生活方式的服务。

当我调用container.Verify()时,出现有关生活方式不匹配的诊断错误。

导致问题的临时服务已注入到其他临时服务中,因此在继续进行整个项目范围之前,我需要询问一下。为什么从任何生活方式的范围到短暂性依赖都是一个问题?每次注入瞬态时,都会对它们进行新的更新,因此不会有其他干扰。本质上,瞬态对象的生存期由注入的服务决定。

另外,我已经从这里阅读了有关此主题的文档,并且我确实理解了为什么您不希望单例依赖于范围服务,但是肯定依赖于瞬态始终是安全的吗?

史蒂文

每次注入瞬态时,都会对它们进行新的更新,因此不会有其他干扰。

每次您从容器中请求瞬态时,都会对其进行更新,但是一旦将瞬态注入到组件中,它们将在该组件存在的整个过程中一直存在。因此,如果使用组件是单例,这意味着它将拖动所有依赖项,实际上也使它们成为单例。当您查看通常如何实现依赖项注入时,此行为将变得显而易见:

public class SomeComponent
{
    private readonly ILogger logger;
    private readonly IService service;

    public SomeComponent(ILogger logger, IService service) {
        this.logger = logger;
        this.service = service;
    }
}

如您所见,依赖项存储在组件的私有字段中,这将使它们在生命周期内一直存在,SomeComponent并且SomeComponent将继续使用相同的依赖项。

本质上,瞬态对象的生存期由注入的服务来控制。

究竟; 一个组件的生活方式至少与它的消费者一样长。但是,一个依赖项可能有多个具有不同生活方式的消费者,这使得很难看到该依赖项的寿命。当注入到使用者1中时,它可能在请求的持续时间内有效,而注入到使用者2中的该依赖项的另一个实例将与应用程序一样有效。

就像作用域实例一样,临时注册通常也不是线程安全的。否则,您将把它们注册为单例。保持瞬态生存更长的时间显然会导致并发错误或与陈旧数据相关的错误。这就是为什么Simple Injector默认情况下不允许这样做并引发异常的原因。

与Simple Injector相比,您可能会对Autofac如何定义其生活方式感到困惑。Autofac不包含瞬态生活方式。相反,它有一种InstancePerDependency生活方式。从技术上讲,这与瞬态相同,但意图却大不相同。InstancePerDependency您说:“无论生活方式如何,该组件的寿命都应与其消费者一样长”。在某些情况下,这是有道理的,但是通过这样做,您实际上忽略了房间里的大象,而且我发现缺乏检测是常见的错误来源。在大多数情况下,如果您不关心组件的生活方式,则意味着应将其注册为单例-而不是InstancePerDependency

Simple Injector不允许将瞬态注入到有作用域的实例中的原因是,有作用域的实例也可以生存很长时间(取决于应用程序),并且您不能总是假定瞬态可以安全地注入到有作用域的使用者中。

最后,所有这些都是关于传达代码意图的。如果组件是无状态的或线程安全的,则应将其注册为单例。它不是线程安全的,您可以将其注册为作用域或临时的。这使任何阅读配置的人都清楚知道他应该如何处理此类组件,并且它使Simple Injector可以为您检测任何配置错误。

当Simple Injector为您检测到错误配置时,我得出的结论是,当您的系统是围绕纯粹由单例组件组成的对象图进行设计时,可以大大简化您的DI配置。在这里表达了这些想法这将消除我们在进行依赖注入时所面临的许多复杂性,甚至比DI本身已经更快地公开了违反SOLID原则的情况。

在继续进行整个项目之前

我不建议这样做。通常,您会看到应用程序中只有某些“叶子组件”是有作用域的(例如DbContext)。这些范围内的组件不依赖于许多其他组件。您编写的组件通常应该是无状态的,不需要任何缓存。因此,在使对象图单例成为(但不是)选项的情况下,我通常会使尽可能多的对象图成为瞬态对象,并且只有少数几个叶组件处于范围内。由于瞬态可以安全地依赖于作用域实例,因此一切都会按预期进行。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当作用域变量依赖于AngularJS中的服务时,何时更新?

如何使用Simple Injector从ValidationContext获得服务?

Simple Injector中的异步工厂

无法使用单例的作用域服务

为什么我的ViewModel不应该依赖于服务的具体实现?

如何在 Simple Injector 中构建 UnitOfWork 作用域对象图

EmberJS:全局类函数使用Ember-Simple-Auth依赖于会话变量。最佳实践?

使用Simple Injector的Update-Database,不带服务。AddDbContext <>()

使用Simple Injector的asp.net Core Web API服务的正确DefaultScopedLifestyle是什么?

在Simple Injector中以原始配置依赖项注册装饰器

在 Simple Injector 中根据消费者服务类型注册装饰器条件

如何注入具有单例作用域依赖性的Grails 2.4.x服务?

创建单例时,为什么要重复单例中的作用域?

Abap:什么是“ SIMPLE”类型?

错误:在项目“应用”中,已解决的Google Play服务库依赖项依赖于另一个

ContextDependent实例作为Simple Injector中的Singleton

延迟在Simple Injector中创建实例

为什么sudo依赖于vi?

对于WPF窗口介体服务,使用Simple Injector通过键解析实例的替代方法是什么?

单例服务可以使用(作用域)的dbContext吗?

在.NetCore中使用瞬态或作用域或单例的困惑

如何使sysv服务依赖于systemd服务?

系统服务可以依赖于远程系统服务吗?

使用依赖于另一个服务中的服务的管道

InvalidOperationException:无法在Blazor中使用单例'... IAuthentication'中的作用域服务'Microsoft.JSInterop.IJSRuntime'

无法使用单例“ Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor”中的作用域服务“ MyDbContext”

为什么在开发环境中仅出现作用域服务解析错误?

使用Owin和Simple Injector进行UserManager依赖项注入

如何使用 Simple Injector 向基类注入依赖项?