【发布时间】:2023-03-25 01:01:01
【问题描述】:
我正在处理一个我认为我理解其原因的 DI 问题,但我需要一些建议来解决。
我已经构建了一个与 Sql 对话的独立程序集(称为此程序集 a),以及另一个包含业务逻辑的程序集(称为此程序集 b)。我在 b 程序集中为 db 类创建了一个接口。由于接口不是 db 程序集的一部分,因此我不需要对 db 项目的任何引用,如果我想在运行时运行单元测试而不是程序集,我可以加载对 db 程序集或存根的引用需要了解对方。
我可以在编译的业务逻辑库中编写如下代码:(假设 a 和 b 是它们各自程序集中的命名空间)
a.IDatabaseClass db_class = (a.IDatabase)new b.Database();
但是,当我尝试运行它时,我得到一个无效的强制转换异常。我认为它可以编译,因为接口与类完美匹配,但在运行时失败,因为对象签名在 Database 类的继承链中看不到 IDatabase。
在 c++ 中,您可以随意转换任何东西,但 c# 在转换对象指针方面要严格一些。即使该类具有所有正确的函数签名,它还是因为对象不匹配而崩溃。
现在我可以将 db 对象接口与 db 对象放在程序集中,但是业务逻辑需要对 db 程序集的引用。此外,这只会在未来产生复杂性,因为如果我在单元测试中编写存根 db 对象,我需要一个对 db 程序集的引用,只是为了我将在我的测试存根对象中使用的接口。这样做似乎并没有解开耦合...
我可以将所有接口放在作为 db 程序集、业务逻辑和单元测试的父级的第三个程序集中。这就是解决循环依赖问题的方法。但是,这会将 db 程序集与父程序集联系在一起,并使其与其他项目一起使用的模块化程度大大降低。
我愿意接受有关如何设置每个程序集以便它们独立运行并可用于 DI 的建议。我想我可以将测试存根对象保存在与真实代码相同的程序集中,但这似乎很奇怪。
解决方案:下面的回复之一评论说,我所拍摄的基本上是界面的鸭式打字。 C# 目前不支持鸭子类型,但我认为这可能是可能的,因为接口实现的行为方式类似于您可能称之为部分类指针(或更准确地说,可能是函数指针的集合)。我的实验告诉我不是这样,这就是原因。
所以在 Redmond 将“more mallard”放入 c# 之前,看起来我们无法完全达到最终优雅的解耦程序集水平。
【问题讨论】:
-
能否确认sql库引用的是业务逻辑库?那
b.Database实现a.IDatabase?或者,这些库是严格独立的吗? -
再次阅读帖子后发现它们是完全独立的库。我肯定会选择“第三图书馆”的方法。它绝对是最干净的,我不同意仅仅引用一个暴露接口的库会创建你的 sql 库的紧密耦合。
-
你是对的,它们都是独立的(或可能是)相互独立的。我希望能够使用 DI 将任何一个程序集与另一个程序集完全断开,并且 exe 或单元测试将在运行时传输数据。似乎 c# 试图通过强类型来使我的代码更安全,这阻碍了我实现这一理想。
标签: c# unit-testing dependency-injection