gpt4 book ai didi

c# - IoC 范式中的非平凡构造函数是一件坏事吗?

转载 作者:行者123 更新时间:2023-11-30 17:12:32 25 4
gpt4 key购买 nike

我在我的 C# 项目中使用依赖注入(inject),通常一切正常。尽管如此,我经常听到这样的规则“构造函数必须只包含微不足道的操作——分配依赖关系,什么都不做”,即:

//dependencies
interface IMyFooDependency
{
string GetBuzz();
int DoOtherStuff();
}

interface IMyBarDependency
{
void CrunchMe();
}

//consumer
class MyNiceConsumer
{
private readonly IMyFooDependency foo;
private readonly IMyBarDependency bar;
private /*readonly*/ string buzz;//<---question here
MyNiceConsumer(IMyFooDependency foo, IMyBarDependency bar)
{
//omitting null checks
this.foo = foo;
this.bar = bar;
//OR
this.buzz = foo.GetBuzz();//is this a bad thing to do?
}
}

UPD:假设 IMyFooDependency 不能替换为 GetBuzz(),因为在那种情况下答案很明显:“做不依赖于 foo”。

UPD2:请理解,这个问题不是关于消除假设代码中 foo 的依赖,而是关于理解良好构造函数设计的原则。

所以,我的问题如下:这真的是一个坏模式在构造函数中包含非平凡的逻辑吗(即获取buzz值,根据依赖关系进行一些计算.)

就我个人而言,除非需要延迟加载,否则我会在构造函数中包含 foo.GetBuzz(),因为对象需要在调用其构造函数后进行初始化。

我看到的唯一缺点:通过包含非平凡的逻辑,你会增加可能出错的地方的数量,并且你会从你的 IoC 容器中得到一个混淆的错误消息(但同样的事情会发生在无效参数的情况下, 所以缺点很小)

关于省略非平凡构造函数的任何其他注意事项?

最佳答案

如果您只需要 IMyFooDependency 来创建 buzz,那么您实际上需要 buzz:

class MyNiceConsumer
{
private readonly IMyBarDependency bar;
private readonly string buzz;

MyNiceConsumer(string buzz, IMyBarDependency bar)
{
this.buzz = buzz;
this.bar = bar;
}
}

并以这种方式创建 nice consumer 的实例:

new MyNiceConsumer(foo.GetBuzz(), bar);

我看不出在将参数传递给构造函数之前获取 buzz 与在构造函数中获取它之间有什么区别。将从存储库返回相同的值。因此,您不需要依赖存储库。

更新:从技术上讲,构造函数中的复杂初始化逻辑没有任何问题。查看 winforms InitializeComponent 方法,其中创建、初始化所有控件并将其添加到窗体。

但它违反了SRP(创建和初始化)并且很难测试。您可以阅读有关此缺陷的更多信息 on writing testable code guide .主要思想:

Do not create collaborators in your constructor, but pass them in. (Don’t look for things! Ask for things!)

关于c# - IoC 范式中的非平凡构造函数是一件坏事吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10591310/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com