多次引用同一个类库。

时间:2022-07-15 19:38:19

Let's assume that 2 years ago, I wrote a .NET class library, say mylib.dll, that heavily depends on an external library, say foo.dll, which is open sourced, MIT licensed (that's relevant, read on).

假设两年前,我写了一个。net类库,mylib。dll,很大程度上依赖于外部库,比如foo。它是开源的,麻省理工学院授权的(这是相关的,请继续阅读)。

A lot of customers used my library, along with its dependency assembly. The package was mylib.dll with foo.dll.

许多客户使用了我的库以及它的依赖程序集。这个包是mylib。与foo.dll dll。

Days went by, and the creators of foo.dll broke their API, and now they deployed a new version of their library. This new version includes most of the types that were included in the old version, but some of the methods are missing, or changed.

日子一天天过去,福的创造者也来了。dll破坏了它们的API,现在他们部署了一个新版本的库。这个新版本包含了旧版本中包含的大多数类型,但是有些方法丢失或更改了。

The Problem

Some potential consumers already use foo.dll in its new version in their application, for their own uses. When I supply them mylib.dll, they can't use it. They can't even have a successful build, because mylib.dll wants the old version of foo.dll with its old methods and signatures.

一些潜在的消费者已经使用了foo。dll在其新版本中的应用程序,供自己使用。当我供给他们的时候。dll,他们不能使用它。他们甚至不能成功构建,因为mylib。dll需要旧版本的foo。dll的旧方法和签名。

How to overcome this problem?

I'd like to have a forward compatible solution, so that this issue is not raised again. So I thought about several things:

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

  1. Update my source code to use the new version of foo.dll. But that's a lot of work and time consuming. In addition, that's not forward compatible, since this issue might be raised again some day.
  2. 更新我的源代码以使用新版本的foo.dll。但这需要大量的工作和时间。此外,这不是向前兼容的,因为这个问题可能会在某天再次提出。
  3. Since I have the source of the exact version of foo.dll, perhaps I can easily change its namespace and rebuild the whole thing. This way I can enjoy my own version of foo.dll, and that's legal since its license is MIT. I can name the modified assembly mylib.foo.dll or something like that. I can even merge the whole thing using ILMerge to something like mylib.merged.dll.
  4. 因为我有确切版本的foo。dll,也许我可以很容易地改变它的名称空间并重建整个东西。这样我就可以享受我自己版本的foo。dll,这是合法的,因为它的许可是MIT。我可以命名修改后的程序集mylib.foo。dll之类的。我甚至可以用ILMerge把整个事情合并到mylib.merged.dll中。
  5. Redesign mylib.dll so that the needed functionality from foo.dll is separated into an interface and an implementation. In terms of engineering, that's the most elegant solution. In terms of time, that's a disaster and therefore cannot be considered a real solution.
  6. 重新设计mylib。从foo中获取所需的功能。dll被分成一个接口和一个实现。在工程方面,这是最优雅的解决方案。就时间而言,这是一场灾难,因此不能被认为是真正的解决方案。

My Question

To accomplish #2 above, is there a short way of changing the namespace of a given source code?

为了实现上面的#2,是否有一种短的方法来改变给定源代码的名称空间?

2 个解决方案

#1


0  

If you do not use many of the methods of the old foo.dll that went missing in the new one, a viable solution could be to link your code to the new foo.dll, and make something like mylib.foo.legacy.dll that contains the missing functions, which you can copy from the old foo source since it's open source and MIT licenced.

如果您不使用老foo的许多方法。在新版本中丢失的dll,一个可行的解决方案可能是将您的代码链接到新的foo。dll,做一些类似mylib.foo.legacy的东西。包含缺失函数的dll,你可以从旧的foo源代码中复制它,因为它是开放源码的,并且是MIT许可的。

No matter what you do, take the newest version of foo.dll as base, it's very unlikely that the authors will go back to the old functionality. If you mark the legacy methods you copied from the old dll with the [obsolete] attribute, you will get compile warnings showing you where the old functions are still referenced. You could then over time work towards removing these references until the legacy dll can be completely removed.

不管你做什么,都要使用最新版本的foo。作为基础,作者不太可能回到旧的功能。如果将从旧dll中复制的遗留方法标记为[过时]属性,则会得到编译警告,显示旧函数仍然被引用的地方。然后,您可以逐步删除这些引用,直到遗留dll完全被删除。

#2


0  

Aha! Yeah - this is a common pain of consumers of popular open source libs such as nlog, newtonsoft etc etc.

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

1. ALLOW MULTIPLE FOO.DLL(s)

1。允许多个FOO.DLL(s)

Your problem stems from the fact that your output directory can only contain one copy of a DLL (because all versions share the same file name). Some products put the version number into the DLL file name to solve this - but I think this is ugly. You could use assembly binding redirects to store your DLLs dependencies in a bin/subfolder to prevent overwriting - but this is a bit of a hack better solved with the following solution...

您的问题源于这样一个事实:您的输出目录只能包含一个DLL的副本(因为所有版本都共享同一个文件名)。有些产品把版本号放到DLL文件的名称中来解决这个问题,但我认为这很难看。您可以使用汇编绑定重定向将dll的依赖项存储在一个bin/子文件夹中,以防止重写——但是这是一个更好的解决方案,有以下解决方案……

2. ILMERGE

2。ILMERGE

The easiest solution for your customers, is for you to package your assembly and its dependencies into a multi-module DLL - i.e. use ILMerge to MERGE foo.dll into your mylib.dll (yes, a DLL can contain multiple assemblies) - then your product appears to be dependency-less (it's not really, its dependencies are just supplied all in the one DLL! Nice!).

对于您的客户来说,最简单的解决方案是将程序集和它的依赖项打包到一个多模块DLL中,即使用ILMerge合并foo。dll mylib。dll(是的,一个dll可以包含多个程序集)-然后你的产品看起来是不依赖的(它不是真的,它的依赖只是在一个dll中提供的!)不错!)

This is a much nicer solution than trying to recompile foo.dll, or namespace search/replace because you don't have to mess with the dependency source code and risk breaking it... plus as soon as you start changing 3rd party source code, you have to maintain those changes - when they release a new version... here you go searching/replacing again...

这是一个比重新编译foo更好的解决方案。dll,或者名称空间搜索/替换,因为您不需要处理依赖源代码,并且有可能破坏它……另外,当你开始修改第三方源代码时,你必须保持这些变化——当他们发布新版本时……在这里你又去寻找/替换……

Problem solved.

问题解决了。

WARNING: Remember, if your mylib.dll returned types declared in foo.dll to the calling program (your customers' programs) they may get a class-cast exception because their DLL is expecting a different version of the type. Hence, this solution is only recommended if your dependency on foo.dll is black-box (not exposed publicly). However, I expect this is not a problem for you, or your wouldn't be considering moving the FOO types into a different namespace.

警告:请记住,如果您的mylib。在foo中声明的dll返回类型。dll对调用程序(您的客户程序)可能会有一个类-cast异常,因为他们的dll期望的类型是不同的版本。因此,只有在对foo的依赖时,才建议使用此解决方案。dll是黑盒(不公开)。但是,我希望这对您来说不是问题,或者您不会考虑将FOO类型转换为不同的名称空间。

#1


0  

If you do not use many of the methods of the old foo.dll that went missing in the new one, a viable solution could be to link your code to the new foo.dll, and make something like mylib.foo.legacy.dll that contains the missing functions, which you can copy from the old foo source since it's open source and MIT licenced.

如果您不使用老foo的许多方法。在新版本中丢失的dll,一个可行的解决方案可能是将您的代码链接到新的foo。dll,做一些类似mylib.foo.legacy的东西。包含缺失函数的dll,你可以从旧的foo源代码中复制它,因为它是开放源码的,并且是MIT许可的。

No matter what you do, take the newest version of foo.dll as base, it's very unlikely that the authors will go back to the old functionality. If you mark the legacy methods you copied from the old dll with the [obsolete] attribute, you will get compile warnings showing you where the old functions are still referenced. You could then over time work towards removing these references until the legacy dll can be completely removed.

不管你做什么,都要使用最新版本的foo。作为基础,作者不太可能回到旧的功能。如果将从旧dll中复制的遗留方法标记为[过时]属性,则会得到编译警告,显示旧函数仍然被引用的地方。然后,您可以逐步删除这些引用,直到遗留dll完全被删除。

#2


0  

Aha! Yeah - this is a common pain of consumers of popular open source libs such as nlog, newtonsoft etc etc.

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

1. ALLOW MULTIPLE FOO.DLL(s)

1。允许多个FOO.DLL(s)

Your problem stems from the fact that your output directory can only contain one copy of a DLL (because all versions share the same file name). Some products put the version number into the DLL file name to solve this - but I think this is ugly. You could use assembly binding redirects to store your DLLs dependencies in a bin/subfolder to prevent overwriting - but this is a bit of a hack better solved with the following solution...

您的问题源于这样一个事实:您的输出目录只能包含一个DLL的副本(因为所有版本都共享同一个文件名)。有些产品把版本号放到DLL文件的名称中来解决这个问题,但我认为这很难看。您可以使用汇编绑定重定向将dll的依赖项存储在一个bin/子文件夹中,以防止重写——但是这是一个更好的解决方案,有以下解决方案……

2. ILMERGE

2。ILMERGE

The easiest solution for your customers, is for you to package your assembly and its dependencies into a multi-module DLL - i.e. use ILMerge to MERGE foo.dll into your mylib.dll (yes, a DLL can contain multiple assemblies) - then your product appears to be dependency-less (it's not really, its dependencies are just supplied all in the one DLL! Nice!).

对于您的客户来说,最简单的解决方案是将程序集和它的依赖项打包到一个多模块DLL中,即使用ILMerge合并foo。dll mylib。dll(是的,一个dll可以包含多个程序集)-然后你的产品看起来是不依赖的(它不是真的,它的依赖只是在一个dll中提供的!)不错!)

This is a much nicer solution than trying to recompile foo.dll, or namespace search/replace because you don't have to mess with the dependency source code and risk breaking it... plus as soon as you start changing 3rd party source code, you have to maintain those changes - when they release a new version... here you go searching/replacing again...

这是一个比重新编译foo更好的解决方案。dll,或者名称空间搜索/替换,因为您不需要处理依赖源代码,并且有可能破坏它……另外,当你开始修改第三方源代码时,你必须保持这些变化——当他们发布新版本时……在这里你又去寻找/替换……

Problem solved.

问题解决了。

WARNING: Remember, if your mylib.dll returned types declared in foo.dll to the calling program (your customers' programs) they may get a class-cast exception because their DLL is expecting a different version of the type. Hence, this solution is only recommended if your dependency on foo.dll is black-box (not exposed publicly). However, I expect this is not a problem for you, or your wouldn't be considering moving the FOO types into a different namespace.

警告:请记住,如果您的mylib。在foo中声明的dll返回类型。dll对调用程序(您的客户程序)可能会有一个类-cast异常,因为他们的dll期望的类型是不同的版本。因此,只有在对foo的依赖时,才建议使用此解决方案。dll是黑盒(不公开)。但是,我希望这对您来说不是问题,或者您不会考虑将FOO类型转换为不同的名称空间。