构造函数过度注入类型集中于收集数据

时间:2013-03-21 06:51:28

标签: c# dependency-injection constructor

我知道这个论点在S.O.上有很好的涵盖,特别是在

Why not use an IoC container to resolve dependencies for entities/business objects?

还有其他问题;但怀疑仍然存在。

我使用了收集数据的类型而不是实体业务对象,以使问题集中在原则上。

所以,如果我这样的类型依赖于这样的primitive data(甚至更多的字段):

public class Animal {
  private readonly string name;
  private readonly string nickname;
  private readonly int weight;
  private readonly int heightAtWithers:
  private readonly Color mainColor;
  private raadonly bool isMale;
  private readonly bool isAggressive;

  public Animal(string name, string nickname, int weight,
                int heightAtWithers, Color mainColor,
                bool is Male, bool isAggressive)
  {
    // remainder omitted
  }

  public string Name { get { return this.name; } }

  // remainder omitted
}

这是构造函数过度注入的情况吗?

Mark Seemann书中建议保持较低的依赖数,2到4(如果我没有错)。

对于此反模式不适用的此类型是否可能?

2 个答案:

答案 0 :(得分:8)

在正常意义上,这些并非真正的依赖 - 它们是实体的数据。它不像那些东西提供多态服务等。我通常不会期望依赖注入框架(或IoC容器)来创建这样的对象 - 通常它将是ORM或手的一部分写代码。

调用这样的构造函数确实有点痛苦,如果你想提供的默认值也变得棘手。如果您使用C#4或更高版本,可选参数和命名参数可以提供帮助。 (它们确实要求在编译时知道默认值,请注意。)

另一种方法是创建一个具有相关默认值的可变构建器类型。我通常把它变成一个嵌套类。您可以为它提供一个无参数构造函数,只需在构建构建器时验证所需的所有内容,或者为构造函数提供所有必需的值,并保留可选值的属性。然后,您可以使用对象初始值设定项来愉快地创建实例:

var animal = new Animal.Builder("Frederick") {
                 NickName = "Freddie",
                 Weight = 10,
                 MainColor = Color.Brown
             }).Build();

编写构建器会刺激锅炉板工作,但它可能很有用。如果您发现在构造实例时始终具有相关信息,那么坚持使用当前的构造函数可能更简单。考虑使用命名参数使每个参数的含义更清晰,特别是当存在多个具有相同类型的参数时:

var animal = new Animal(name: "Frederick", nickname: "Freddie",
                        weight: 10, heightAtWithers: 20,
                        Color.Brown, isMale:true, isAggressive: false);

答案 1 :(得分:5)

IIRC,当Mark谈到Constructor Over-Injection时,它违反SRP违规行为。

依赖于很多其他服务的课程很可能不止一件事 对于依赖于大​​量原语的类来说,情况不一定如此。

话虽如此,原始数据类型的依赖关系和“数据持有者类”的数据是两回事。

将您的课程与您所链接文章中描述的课程进行比较:
DbChartReader 需要 top才能完成工作 - 这是一种依赖。
Animal没有做任何工作。通过构造函数传入的数据基本上是 对象 - 构造函数参数就是:data。