跨程序集的依赖项注入&;命名空间

本文关键字:amp 命名空间 注入 程序集 依赖 | 更新日期: 2023-09-27 18:25:45

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

我构建了一个与Sql对话的独立程序集(将此程序集称为a),以及另一个包含业务逻辑的程序集(称此程序集为b)。我为b程序集中的db类创建了一个接口。由于接口不是数据库程序集的一部分,所以我不需要对数据库项目的任何引用,如果我想在运行时运行单元测试,并且两个程序集都不需要知道另一个程序集,我可以加载对数据库程序集或存根的引用。

我可以在编译的业务逻辑库中编写如下代码:(假设a和b是各自程序集中的名称空间)

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

但是,当我尝试运行此操作时,会得到一个无效的强制转换异常。我认为它编译是因为接口与类完全匹配,但在运行时失败是因为对象签名在Database类的继承链中看不到IDatabase。

在c++中,可以随心所欲地进行任何类型的强制转换,但c#对强制转换对象指针有点严格。尽管该类具有所有正确的函数签名,但由于对象不匹配,它会爆炸。

现在我可以将db对象接口与db对象一起放在程序集中,但业务逻辑需要对db程序集的引用。此外,这只会造成复杂的情况,因为如果我在单元测试中编写一个存根数据库对象,我需要一个对数据库组件的引用,只用于我将在测试存根对象中使用的接口。这样做似乎并没有解开耦合。。。

我可以将所有接口放在第三个程序集中,该程序集是db程序集、业务逻辑和单元测试的父级。这就是解决循环依赖性问题的方法。然而,这将db程序集与父程序集联系在一起,并使其与其他项目一起使用的模块化程度大大降低。

我对如何设置每个程序集以便它们独立运行并可用于DI持开放态度。我想我可以将测试存根对象与实际代码保持在同一个程序集中,但这似乎很奇怪。

解决方案:下面的一个回复评论说,我拍摄的基本上是为界面打字。C#目前不支持鸭子类型,但我认为这可能是可能的,因为接口实现的行为方式与您可能称之为分部类指针(或者更准确地说,可能是函数指针的集合)的方式类似。我的实验向我展示了另一种情况,这就是为什么。

因此,在Redmond将"更多绿头鸭"放入c#之前,我们似乎无法完全达到解耦组件的最终优雅级别。

跨程序集的依赖项注入&;命名空间

创建一个包含通用接口的引用库。通过这种方式,您将拥有一个与所有实现无关的逻辑的公共源。

我没有经验相信这是一个明确的声明,但我强烈怀疑,当你谈论引用特定接口的单个类型及其行为时,耦合主要是一个问题。程序集没有使耦合成为问题的那种特殊性。

编辑1

让我修改并延长。一个程序集必须引用另一个,或者两者都必须引用公共程序集。C#没有鸭子接口,如果真是这样的话。

现在,我认为最佳实践是将业务逻辑与外部接口隔离,因此,如果要做任何事情,都应该将业务逻辑从DB实现中隔离。所以DB/Application程序集引用业务逻辑,但不是相反。

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

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

根据依赖反转原理,"客户端[…]拥有抽象接口"(APPP,第11章),因此没有理由将接口放在第三个库中。