我正在研究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#当前不支持duck typing,但我认为它可能是可能的,因为接口实现的行为类似于你可能称之为部分类指针的方式(或者更准确地说,是函数指针的集合).我的实验向我展示了其他情况,这就是原因.
所以,直到Redmond将"更多的野鸭"放入c#,看起来我们无法完全达到最终优雅的解耦组件.
创建包含常用接口的参考库.这样,您将拥有所有与实现无关的逻辑的公共源.
我没有经验使自己有信心将其作为一个明确的陈述,但我强烈怀疑,当您谈论引用特定接口的个别类型及其行为时,耦合主要是一个问题.程序集不具有使耦合问题的相同特异性.
编辑1让我修改和扩展.一个组件必须引用另一个组件,或者两者都必须引用一个公共组件.如果这是一件事,C#没有鸭子接口.
现在我认为最好的做法是将业务逻辑与外部接口隔离开来,所以如果你要做任何事情,你应该将业务逻辑与数据库实现隔离开来.所以DB/Application程序集引用业务逻辑,但不是相反.
以下是有关依赖关系方向的更多信息.