代码之家  ›  专栏  ›  技术社区  ›  Jason Young

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

  •  4
  • Jason Young  · 技术社区  · 15 年前

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

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

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

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

    其他的选择包括使用一个允许我传递额外的构造函数参数的IOC容器,或者只在顶层构建我需要的类,而不使用依赖注入。

    对于这类问题,是否有公认的标准模式?

    2 回复  |  直到 15 年前
        1
  •  4
  •   Mark Seemann    15 年前

    根据你的需要,你可以走两条路线。

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

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

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

    缺点是你的灵活性变差了。您将无法用另一个实现任意地替换一个实现(但同样,您可能不需要这种灵活性)。

    即使UI被锁定在具体的实现中,这并不意味着域模型本身在 其他应用 .

    2。添加抽象工厂

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

    工厂的创建方法可以将端口号作为输入,因此这个抽象在UI子层中是最好的。

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

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

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

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

        2
  •  0
  •   Reed Copsey    15 年前

    大多数国际奥委会集装箱都有某种形式的 Constructor Injection 这将允许您的IOC容器将模拟的COM端口传递到您的类中进行单元测试。这似乎是最干净的解决方案。

    我将避免添加“start”方法等。更好的做法是(如果可能的话)始终使类处于有效状态,并使用start方法切换到无参数构造函数会使这些调用之间的类无效。这样做是为了让测试变得更加困难(这会使测试变得更好)。