【问题标题】:What is the best strategy for Dependency Injection of User Input?用户输入依赖注入的最佳策略是什么?
【发布时间】:2009-11-05 19:20:30
【问题描述】:

我使用了相当多的依赖注入,但我想了解如何在运行时处理来自用户的信息。

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

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

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

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

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

【问题讨论】:

    标签: dependency-injection inversion-of-control design-patterns


    【解决方案1】:

    您可以选择两条路线,具体取决于您的需要。

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

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

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

    缺点是您获得的灵活性较低。您将无法随意将一种实现替换为另一种实现(但话又说回来,您可能不需要这种灵活性)。

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

    2。添加抽象工厂

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

    工厂的Create方法可以将端口号作为输入,所以这个抽象最好属于UI子层。

    public abstract class MyFactory
    {
        public abstract IMyInterface Create(int portNumber);
    }
    

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

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

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

    【讨论】:

      【解决方案2】:

      大多数 IoC 容器都有某种形式的 Constructor Injection,这将允许您的 IoC 容器将模拟的 COM 端口传递到您的类中以进行单元测试。这似乎是最干净的解决方案。

      我会避免添加“Start”方法等。更好的做法是(如果可能)始终让您的类处于有效状态,并使用 start 方法切换到无参数构造函数会使您的类在这些调用之间无效.这样做以启用测试只会使您的课程更难测试(这应该会更好)。

      【讨论】:

      • 对不起,我应该更清楚。 com 端口只是一个数字。测试不是问题,因为我可以创建类的模拟版本。我不提前知道com端口,我从用户那里得到它。既然如此,让 UI 使用接口似乎有点愚蠢,因为它需要一个需要 com 端口的实现。
      猜你喜欢
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      相关资源
      最近更新 更多