对同一类库的多个引用

时间:2013-04-10 08:10:14

标签: .net dependencies versioning forward-compatibility

让我们假设2年前,我写了一个.NET类库,比如mylib.dll,它很大程度上取决于外部库,比如foo.dll,它是开源的,MIT许可的(相关的) ,请继续阅读。

许多客户使用我的库及其依赖程序集。该软件包为mylib.dll foo.dll

几天过去了,foo.dll的创建者破坏了他们的API,现在他们部署了新版本的库。此新版本包含旧版本中包含的大多数类型,但某些方法已丢失或更改。

问题

一些潜在消费者已经在其应用程序中使用foo.dll新版本,以供自己使用。当我提供mylib.dll时,他们无法使用它。他们甚至无法成功构建,因为mylib.dll希望旧版本的foo.dll具有旧方法和签名。

如何克服这个问题?

我想要一个前向兼容的解决方案,以便不再提出此问题。所以我想了几件事:

  1. 更新我的源代码以使用新版本的foo.dll。但这需要大量的工作和时间。此外,这不是向前兼容的,因为有一天可能会再次提出此问题。
  2. 由于我拥有foo.dll的确切版本的来源,或许我可以轻松地更改其命名空间并重建整个事物。通过这种方式,我可以享受我自己的foo.dll版本,这是合法的,因为它的许可是麻省理工学院。我可以命名修改后的程序集mylib.foo.dll或类似的东西。我甚至可以使用ILMerge将整个内容合并到mylib.merged.dll
  3. 之类的内容中
  4. 重新设计mylib.dll,以便将foo.dll所需的功能分为界面和实现。在工程方面,这是最优雅的解决方案。就时间而言,这是一场灾难,因此不能被视为真正的解决方案。
  5. 我的问题

    要完成上面的#2,是否有一种简短的方法来更改给定源代码的命名空间?

2 个答案:

答案 0 :(得分:0)

如果您没有使用新版本中遗漏的旧foo.dll的许多方法,那么可行的解决方案是将您的代码链接到新的foo.dll,并制作类似的内容mylib.foo.legacy.dll包含缺少的功能,您可以从旧的foo来源复制,因为它的开源和MIT已获得许可。

无论你做什么,以最新版本的foo.dll为基础,作者都不太可能回到旧功能。如果您使用[obsolete]属性标记从旧dll复制的旧方法,则会收到编译警告,显示仍旧引用旧函数的位置。然后,您可以随着时间的推移去除这些引用,直到可以完全删除旧版dll。

答案 1 :(得分:0)

啊哈!是的 - 这是流行的开源库的消费者的常见痛苦,如nlog,newtonsoft等等。

<强> 1。允许多个FOO.DLL

您的问题源于您的输出目录只能包含DLL的一个副本(因为所有版本共享相同的文件名)。有些产品将版本号放入DLL文件名中来解决这个问题 - 但我认为这很难看。您可以使用程序集绑定重定向将您的DLL依赖项存储在bin /子文件夹中以防止覆盖 - 但这有点像使用以下解决方案更好地解决了...

<强> 2。 ILMERGE

客户最简单的解决方案是将程序集及其依赖项打包到多模块DLL中 - 即将ILMerge to MERGE foo.dll用于mylib.dll(是的,一个DLL可以包含多个程序集) - 然后你的产品似乎是无依赖的(它不是真的,它的依赖只是在一个DLL中提供!很好!)。

这是一个比尝试重新编译foo.dll或命名空间搜索/替换更好的解决方案,因为你不必弄乱依赖源代码并冒险破解它...加上你开始更改第三方源代码,您必须维护这些更改 - 当他们发布新版本时......在这里您再次搜索/替换...

问题解决了。

警告:请记住,如果您的mylib.dll将foo.dll中声明的类型返回给调用程序(您的客户程序),则它们可能会获得类转换异常,因为它们的DLL期望该类型的不同版本。因此,仅当您对foo.dll的依赖是黑盒(未公开)时,才建议使用此解决方案。但是,我希望这对您来说不是问题,或者您不会考虑将FOO类型移动到不同的命名空间。