在高代码重用环境中应用依赖反转时如何在 .Net 中对抽象进行版本化
我有兴趣转向在 .Net 中使用依赖倒置,但遇到了一些令我困惑的事情。我不认为它与 DIP 的特定方法或提供者有关,而是更多可能其他人已经解决的基本问题。我要解决的问题最好按照下面的场景逐步说明。
假设/限制
预先提出的一个相当大的假设或限制是,我的开发团队坚持将我们部署的程序集保留为一个且只有一个程序集版本的规则,特别是版本“1.0.0.0”。到目前为止,为了简单起见,我们不支持将我们开发的任何给定程序集的多个程序集版本部署在服务器上。这可能是限制性的,并且可能有很多很好的理由来摆脱它,但无论如何,这是我们目前使用的规则。因此,考虑到这种做法,继续下面。
设想
- 您有一个 IDoStuff 接口,包含在具有 2 个方法的抽象程序集 Stuff.Abstractions.dll 中。
- 您使用具有 2 种方法的显式实现 IDoStuff 的类来编译组件 A.dll。
- 您将 A.dll 移至生产使用,程序集版本 1.0.0.0,程序集文件版本 1.0.0.0。
- 您将 Interface.dll 移至 prod,程序集版本 1.0.0.0,程序集文件版本 1.0.0.0。
- 一切正常。时间流逝。
- 您将另一个方法(例如“DoMoreStuff”)添加到 IDoStuff 接口,以便不同的组件 B 可以调用它。(牢记接口隔离 OO 原则,假设 DoMoreStuff 方法在这个相对较小的 IDoStuff 接口中是有意义的。)
- 您现在在 Stuff.Abstractions.dll 中拥有带有 3 个方法的 IDoStuff,并且您已经构建了组件 B 以使用新的第 3 个方法。
- 您将 Stuff.Abstractions.dll 移动到生产使用(升级它)、程序集版本 1.0.0.0、程序集文件版本 1.0.0.1。(请注意,文件版本会增加,但程序集版本和强名称保持不变)
- 您将 B.dll 移至生产使用,程序集版本 1.0.0.0,程序集文件版本 1.0.0.17。
- 你不会对 A.dll 做任何事情。您认为此时不需要进行任何更改。
现在,您调用的代码试图在之前工作的同一生产服务器上执行 A.dll。在运行时,依赖反转框架将 IDoStuff 接口解析为 A.dll 中的一个类并尝试创建它。问题是 A.dll 中的类实现了现已灭绝的 2 方法 IDoStuff 接口。正如人们所预料的那样,您会得到一个像这样的异常:
来自程序集“程序集 A.dll 的强名称”的类型“A.dll 中的 IDoStuff 类”中的方法“DoMoreStuff”没有实现。
当我必须向现有接口添加方法时,我可以想到两种方法来处理这种情况:
1) 更新每个使用 Stuff.Abstractions.dll 的功能提供程序集,以实现新的“DoMoreStuff”方法。这似乎是用艰难的方式做事,但以蛮力的方式会很痛苦。
2)弯曲上述假设/限制并开始允许存在多个程序集版本(至少对于抽象定义程序集)。这会有点不同,并在我们的服务器上制作更多的程序集,但它应该允许以下最终状态:
A.dll 依赖于 stuff.abstractions.dll,Assembly 版本 1.0.0.0,Assembly File 版本 1.0.0.22(AFV 与识别构建无关) B.dll 依赖于 stuff.abstractions.dll,Assembly 版本 1.0。 0.1,程序集文件版本 1.0.0.23(AFV 除了识别构建之外无关紧要)两者都能够在同一台服务器上愉快地执行。
如果两个版本的 stuff.abstractions.dll 都安装在服务器上,那么一切都应该很好。A.dll 也不需要更改。每当它接下来需要修改时,您可以选择实现存根并升级接口,或者什么也不做。如果它只需要它们,也许最好将其保留为它首先可以访问的 2 种方法。作为附带的好处,我们知道任何引用 stuff.abstractions.dll,版本 1.0.0.0 的东西只能访问 2 个接口方法,而 1.0.0.1 的用户可以访问 3 个方法。
是否有更好的方法或可接受的部署模式来进行版本控制抽象?
如果您尝试在.Net 中实现依赖倒置方案,是否有更好的方法来处理版本控制抽象?如果你有一个单一的应用程序,它看起来很简单,因为它都包含在内——只需更新界面用户和实施者。我试图解决的特定场景是一个高代码重用环境,其中有许多依赖于许多组件的组件。依赖倒置确实有助于分解事情并使单元测试感觉不像系统测试(由于紧密耦合的层)。