【发布时间】:2015-09-10 10:10:10
【问题描述】:
我正在构建一个 GUI 框架,我目前有很多行(通常在构造函数中)
var renderer = locator.GetService<IRenderer>();
var input = locator.GetService<IMouseInput>();
我获得的那些服务是核心服务,我的意思是,这些服务本质上是被认为是基础的一部分。
我曾考虑过使用构造函数注入,但出现了一些烦恼。
- 我将不得不修改几乎每个构造函数以注入其依赖项,这意味着它甚至可以接收最基本的“服务”。我害怕每个构造函数中有 3 或 4 个参数。
- 但更糟糕的另一件事是,如果框架的最终用户找不到无参数构造函数,他们将不会高兴。您是否认为创建 TextBox 需要您传递它真正需要的所有依赖项?
最终用户可能会被 new TextBox(dep1, dep2, dep3) 淹没。
那么,有没有一种很好的方法可以完全删除服务定位器而不会使其过于复杂?
编辑
在我们正在讨论的团队中,他们仍然希望保持服务定位器争论以下内容。这是对话的片段:
我们不关心 TextBox 实现中的单一职责。我们 不是'写应用程序。这是一个UI框架!它应该 隐藏最终用户的东西和细节,而不是暴露它们。一个流利的文本框构建器?严重地?我们不是在写一些网络请求 处理管道。
我同意他 (Stack Overflow 用户) 写的所有内容,但关于 应用程序。您希望东西尽可能可扩展和可重用的地方。我们有 10 项服务。 到处都在使用它们。如果 我们有 50 个依赖关系和复杂的对象图,我们做不到 任何没有 DI 和东西的东西。关于DI的事情是你有薪水 为了它。所以对我们来说 Service Locator 是免费的 DI 不是 它只是 不可维护 - 通过拥有更复杂的 API,通过拥有落后的 API/ABI 兼容性等。我们在不知道的情况下为服务定位器付费 什么类需要作为它的依赖项以及提供的一些问题 不同实例的不同依赖实现。但我们 也不需要,所以服务定位器是免费的。 DI 不是。
你同意吗?为什么?
【问题讨论】:
-
什么是
IRenderer,为什么它是一个接口?它的寿命是多少?作为一个框架,我实际上认为您希望避免引入 IOC 框架。从性能的角度来看,您确实应该在构造函数中对所有内容进行硬编码。 -
假设您的定位器是全局对象,那么当前的定位器方法有什么问题?
-
定位器错误,因为它隐藏了依赖关系,这是一件坏事。
-
@Aron 对象的生命周期基本上是从应用程序开始到结束。这只是他们每个人的一个实例。它是一个接口,因为它将是跨平台的,并且需要有不同的实现。
-
当你在构造函数中传递所有依赖项时,我看不出构造函数注入方法有什么问题——它比使用服务定位器解决它们要好得多,服务定位器本质上是anti-pattern。使用构造函数注入,您的 API 不会对它们的依赖关系撒谎并使它们显而易见。
标签: c# design-patterns dependency-injection service-locator