【问题标题】:Constructors + Dependency Injection构造函数 + 依赖注入
【发布时间】:2011-02-02 16:46:30
【问题描述】:

如果我正在编写一个具有多个构造函数参数的类,例如:

class A{
    public A(Dependency1 d1, Dependency2 d2, ...){}
}

我通常创建一个“参数持有者”类型的类,例如:

class AArgs{
    public Dependency1 d1 { get; private set; }
    public Dependency2 d2 { get; private set; }
    ...
}

然后:

class A{
    public A(AArgs args){}
}

通常,使用 DI 容器,我可以为依赖项配置构造函数并解决它们,因此当构造函数需要更改时影响最小。

这是否被视为反模式和/或反对这样做的任何论据?

【问题讨论】:

    标签: c# oop dependency-injection


    【解决方案1】:

    好吧,我不会将其称为反模式,但是如果开发人员需要对您的代码库进行更改,那么弄清楚构造函数需要什么会令人困惑,所以“只是为了安全" 他们可以将所有依赖对象传递给构造函数。 哎呀!它是可能真正被滥用的抽象之一。

    【讨论】:

    • hmm - 要使用代码库,开发人员需要初始化 AArgs 类并将其传递给构造函数。 AArgs 可能能够引导他们使用必需参数和可选参数 - 参考:我正在探索这方面的线程 @Pete...
    【解决方案2】:

    Mark Seemann 对此有 blogged

    您传递的是依赖项的集合,而不是每个依赖项本身——基本上它是一种重构。 Mark 认为,通过这样做,您使域中的内容变得明确,而这些内容以前是隐含的。

    【讨论】:

    • 优秀的文章,谢谢。这就是我想要达到的目标,但想知道是否有任何理由不去做......
    • @Sunny:请注意,聚合服务远不止是一个简单地保存一组依赖项以供消费的对象。
    • @Pete - 好的点和聚合服务是我在我的情况下真正需要的。但我的问题更笼统,看看这种模式是否适用于所有类
    • 皮特有一个好点子。制作参数对象可能违反得墨忒耳法则,所以如果可以的话,看看是否也可以将行为封装到其中。
    【解决方案3】:

    这确实为您的依赖项是可选打开了大门。通过为 AArgs 类的每个依赖项设置属性,有人会认为他们只需要填写 Dependency1,一切都会按预期工作。

    通过单独显式列出所有依赖项,您可以清楚地了解类运行所需的内容。如果你的依赖太多以至于构造函数很麻烦,那应该被认为是一种气味,因为你的类可能做的太多了。

    【讨论】:

    • 我同意“明确合同”的说法,但是如果我需要做出改变,我可能会得到重载的构造函数,在这种情况下,我最终会将默认值传递给其他构造函数在一段时间内也只是在维护方面加起来......
    • 为什么需要重载?是否有可选依赖项?如果是这样,您可以考虑对这些使用属性注入。然后很清楚哪些是可选的,哪些是必需的依赖项。其他消耗类 A 的类无论如何都应该注入 A,因此他们不必担心 A 的构造函数。
    • +1 用于作为属性注入注入的选项和作为构造函数注入的其他必需成员。就我而言,我让 AArgs 班级做出这个决定,而这应该是 A 班级的决定
    • @Pete - 再想一想 - 如果 AArgs 打算只传递给 A 类和 A 类,我猜 AArgs 可以决定参数是必需的还是可选的?此外,A 类不会受到影响,因为它可以与作为 AArgs 传入的任何内容一起使用......
    • @Sunny:非常正确。在您的示例中,AArgs 中的“...”并没有完全填充 AArgs 对构造函数等的全部内容。话虽如此,我认为如果 A 类使用显式构造函数和属性直接注入,而不是依赖 AArgs。我个人认为 AArgs 是一种气味,但本身并不是错误的东西。
    【解决方案4】:

    我唯一担心的是你的依赖持有者类AArgs 可能会掩盖你有大量依赖的事实,因此你正在构建的类可能有太多的责任。

    如果您的依赖持有者类 AArgs 通常只有很少的成员(例如,3 个或更少),那么这不是问题。

    【讨论】:

    • 虽然我通常会在 AArgs 中有 2-3 名成员,但人数超过 3 名真的很重要吗?我的意思是,如果确实需要一个类的所有依赖项,那么将它们传递给构造函数是否有罪(不违反单一责任原则)。并不是说我以前遇到过这种情况——我很想听听一个真实的例子
    • 嗯,3 是一个示例数字。如果您的参数是简单的配置参数,那么这不是问题。如果它们是具有行为的复杂对象,我会更加担心。这将指向包含多个职责的包含对象。
    猜你喜欢
    • 2019-04-20
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多