跨程序集和命名空间的dependency injection

我正在研究DI问题,我认为我理解其原因,但我需要一些建议来解决。

我已经构建了一个独立的程序集,它与Sql(称为程序集a)和另一个包含业务逻辑的程序集(称为程序集b)进行对话。 我在b程序集中为db类创建了一个接口。 由于接口不是db程序集的一部分,因此我不需要对db项目的任何引用,如果我想在运行时运行unit testing而不是程序集,我可以加载对db程序集或存根的引用需要知道另一个。

我可以在编译看起来像这样的业务逻辑库中编写代码:(假装a和b是各自程序集中的名称空间)

a.IDatabaseClass db_class = (a.IDatabase)new b.Database(); 

但是当我尝试运行它时,我得到一个无效的强制转换exception。 我认为它编译是因为接口完美匹配类,但在运行时失败,因为对象签名在Database类的inheritance链中没有看到IDatabase。

在c ++中,你可以随心所欲地抛出任何东西,但是c#对于构建对象指针有点严格。 即使该类具有所有正确的函数签名,它也会因为对象不匹配而爆炸。

现在我可以将db对象接口放在具有db对象的程序集中,但是业务逻辑需要对db程序集的引用。 此外,这只会产生复杂性,因为如果我在unit testing中编写存根db对象,我需要对我将在测试存根对象中使用的接口的db程序集的引用。 通过这样做,这似乎并没有解开耦合……

我可以将所有接口放在第三个程序集中,该程序集是db程序集,业务逻辑和unit testing的父级。 这就是解决循环依赖问题的方法。 但是,这会将db程序集绑定到父程序集,并使其与其他项目一起使用的模块化程度要低得多。

我愿意接受有关如何设置每个组件以便它们独立运行并可用于DI的建议。 我想我可以将测试存根对象保存在与真实代码相同的程序集中,但这看起来很奇怪。

解决方案:以下回复中的一个回复说明我拍摄的内容基本上是接口的鸭子类型。 C#当前不支持duck typing,但我认为它可能是可能的,因为接口实现的行为方式类似于你可能称之为部分类指针的方式(或者更准确地说,是函数指针的集合)。 我的实验向我展示了其他情况,这就是原因。

因此,在Redmond将“更多野鸭”放入c#之前,看起来我们无法完全达到最终优雅的解耦组件。

创建包含常用接口的参考库。 这样,您将拥有所有与实现无关的逻辑的公共源。

我没有经验让自己有信心将其作为一个明确的陈述,但我强烈怀疑,当您谈论引用特定接口的个别类型及其行为时,耦合主要是一个问题。 程序集不具有使耦合问题的相同特异性。

编辑1

让我修改和扩展。 一个组件必须引用另一个组件,或者两者必须引用一个公共组件。 如果这是一件事,C#没有鸭子接口。

现在我认为最好的做法是将业务逻辑与外部接口隔离开来,所以如果你要做任何事情,你应该将业务逻辑与数据库实现隔离开来。 因此DB / Application程序集引用业务逻辑,但不是相反。

以下是有关依赖关系方向的更多信息 。

让客户端库( b )定义接口,并从服务器库( a )引用该库。

从依赖倒置原则得出“客户端[…]拥有抽象接口”( APPP ,第11章),因此没有理由将接口放在第三个库中。