2017-10-18 54 views
0

继我在阅读这些指南: https://www.devtrends.co.uk/blog/how-not-to-do-dependency-injection-the-static-or-singleton-container依赖注入 - 尽量避免使用服务定位器

我想尽量避免使用服务定位器。 但另一方面,我没有注册startup.cs文件中的所有类型。我不认为这是正确的,所有这些内部类型在主startup.cs

引用我目前有一个工厂类具有建设者类的集合。 每个构建器类都负责创建特定的对象。 我不想提前创建所有这些构建器类,因为我可能不需要使用它们,创建它们有点繁重。 我看到了一个如何在上面的链接中实现这个功能的例子。但是startup.cs类需要知道所有这些构建器。我不认为这是合适的,我宁愿让工厂阶级成为唯一接触他们的人。我试图了解是否有某种func/action方法可以从startup.cs文件注入到我的工厂类中。这个功能/操作将负责创建/注册建设者,然后我可以在班级工厂内激活这个功能/操作。我想要这个func/action来获得接口/类/可能是构建器的名称,但使用泛型不起作用。我搜索了很多,并没有找到任何解决方案,所以我认为这是不可能的。 似乎我有2个选项: 1.使用服务定位器。这种方式只有工厂类会知道建设者。但是如果将来,如果我想改变DI,我需要“触摸”工厂类(我污染了工厂类)。希望所有的DI代码只能位于startup.cs类中。 2.在startup.cs中注册构建器,但现在startup.cs知道构建器。这有点夫妇的代码,不是真正的单一角色的责任

这将是很好的注入工厂类从startup.cs func /动作将做注册,但工厂类本身激活它。 这可能吗?

+0

在单个类中注册类型没有任何问题。如果你想,你可以将它移动到一个配置文件。 – FCin

+0

那么,我不喜欢配置文件,一般来说,尽量避免它们。在startup.cs中注册所有类型 - 这看起来不太健康。如果我们想要更改构建器,我们需要“离开”工厂/构建器区域并跳转到startup.cs并开始删除/添加注册。我认为这是注册一般组件的好地方,例如Logger/Configuration /等。但不是将我的所有类型加载到一个地方。 – TaLz

+0

您不要每小时更改一次旧的依赖关系,所以我不明白问题是如何去单个文件并更改一行代码。 – FCin

回答

2

我想尽量避免使用服务定位器

大,因为服务定位器is an anti-patttern

不要在startup.cs文件中注册所有类型。

您应该在应用程序的一个“区域”中执行注册:启动路径。这个区域通常被称为Composition Root(组成对象图的地方)。

我不认为这是正确的,所有这些内部类型在主startup.cs引用

不管你如何设计它,启动组件的最不稳定的部分系统和它总是取决于所有应用程序中的其他程序集。直接或传递(通过另一个引用的程序集)。依赖注入的整个想法是尽量减少组件之间的耦合,并且这样做的方法是通过将耦合移动到组合根来集中耦合。然而,通过内部类型,你是分散对象组成,并限制你的灵活性。例如,为这些注册类型应用装饰器或拦截器并在全球范围内控制它变得越来越困难。阅读this question and its two top voted answers了解更多信息。

我不注册的所有种类

其组成的根是太大的问题是不是有效的。人们可以很容易地将组合根分成多个更小的函数或类,它们都驻留在启动程序集中。最重要的是,如果您阅读this,您会明白,明确注册所有类型(a.k.a.“显式注册”)通常毫无意义。在这种情况下,您最好使用没有集装箱的DI(a.k.a. Pure DI)。所有类型明确注册的组合根并不是非常可维护的。 DI Container的强大之处在于其批量注册设施。他们使用反射在几行代码中加载和注册一组完整的类型。添加新类型不会导致您的Composition Root改变,从而为您提供最高的可维护性。

我不想提前创建所有这些建设者类,因为我可能不需要使用它们,创建它们是有点重实例

创作不应该是沉重的。您的injection constructors should be simple和撰写对象图should be reliable。这使得构建甚至是最大的对象图非常快。工厂应减至an absolute minimum

TLDR;

  • 仅在组合根中注册或撰写对象图。
  • 避免使用Service Locator反模式;整个应用程序可以(也应该)纯粹使用构造函数注入来构建。
  • 使注入构造器变得简单,并防止它们做任何事情而不是存储其传入的依赖关系。
  • 不要使用工厂来编写服务,大多数情况下不需要它们。
+0

我不认为这“服务定位器是一种反模式“。在源代码的一些非常罕见的点内解决动态分辨率是非常有用的模式。滥用任何模式是很臭的 - 但这不是模式错误。 – Console

+0

@Console:服务定位器_is_是一种反模式,现在几乎没有关于这个问题的讨论。但是您可能会对什么是和什么不是服务定位器感到困惑。下面是一篇[好文章](http://blog.ploeh.dk/2011/08/25/ServiceLocatorrolesvs.mechanics/),它解释了并非每个使用“Resolve”方法的服务定位器都依赖于它的角色在系统中。 – Steven

+0

那么如果你这样说 - 它符合你所说的;)。我需要使用服务位置机制的架构代码的另一个名称,而不是 – Console