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

jay*_*jay 2 c# constructor dependency-injection

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

为什么不使用IoC容器来解析实体/业务对象的依赖关系?

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

我使用了收集数据而不是实体业务对象的措辞类型来将问题集中在原则上.

所以,如果我这样的类型依赖于这样的原始数据(甚至更多的字段):

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
}
Run Code Online (Sandbox Code Playgroud)

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

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

对于这种反模式不适用的这种类型可能吗?

Jon*_*eet 8

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

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

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

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

编写建造者是刺激锅炉板工作,但它可能是有用的.如果你发现你经常有相关的信息,当你创建实例手,它可能是简单的只是坚持与当前的构造函数.考虑使用命名参数使每个参数的含义更清晰,特别是当存在多个具有相同类型的参数时:

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


Dan*_*rth 5

IIRC,当Mark谈到Constructor Over-Injection时,它是针对SRP违规的.

依赖于很多其他服务的类很可能不止一件事.
对于依赖于大​​量原语的类来说,同样不一定如此.

话虽如此,原始数据类型的依赖性和"数据持有者类"的数据是两个不同的东西.

将您的类与您链接的文章中描述的类进行比较:
DbChartReader 需要 top能够完成其工作 - 它是一个依赖项.
Animal不做任何工作.通过构造函数传入的数据基本上对象 - 构造函数参数就是:data.