用户输入依赖注入的最佳策略是什么?

Jas*_*ung 5 design-patterns dependency-injection inversion-of-control

我使用了大量的依赖注入,但我想在运行时获得有关如何处理用户信息的输入。

我有一个连接到 com 端口的类。我允许用户选择 com 端口号。现在,我将该 com 端口参数作为构造函数参数。原因是该类没有该信息就无法运行,并且它是特定于实现的(此类的模拟版本不需要 com 端口)。

另一种方法是使用一个“Start”方法来接收 com 端口,或者使用一个设置 com 端口的属性。这使得它与 IoC 容器非常兼容,但从类的角度来看它不一定有意义。

看起来逻辑路线与依赖注入设计冲突,但这是因为我的 UI 正在获取特定类型类的信息。

其他替代方法包括使用 IoC 容器,让我传入额外的构造函数参数,或者仅在顶层构造我需要的类而不使用依赖注入。

对于此类问题,是否有普遍接受的标准模式?

Mar*_*ann 5

根据您的需要,您可以选择两条路线。

1. 将 UI 直接连接到您的具体类

这是最简单的选择,但很多时候完全可以接受。虽然您可能有一个具有大量接口和使用 DI 的域模型,但 UI 构成了对象图的组合根,您可以简单地在此处连接您的具体类,包括所需的端口号参数。

好处是这种方法简单且易于理解和实施。

缺点是灵活性较差。您将无法任意地将一种实现替换为另一种实现(但话说回来,您可能不需要这种灵活性)。

即使 UI 锁定到一个具体的实现,这并不意味着域模型本身不能在其他应用程序中重用。

2. 添加抽象工厂

另一种选择是添加另一个间接层。它可以使用抽象工厂来创建实例,而不是让您的 UI 直接创建类。

工厂的Create方法可以将端口号作为输入,因此这种抽象最适合在 UI 子层中使用。

public abstract class MyFactory
{
    public abstract IMyInterface Create(int portNumber);
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以让 DI 容器连接该工厂的实现,该工厂使用端口号并将其作为构造函数参数传递给您的实际实现。其他工厂实现可能会简单地忽略该参数。

这种方法的优点是您不会污染您的 API(或您的具体实现),并且您仍然拥有接口编程为您提供的灵活性。

缺点是它增加了另一层间接。