.NET(C#)应用程序插件的依赖性地狱

4

我目前正在为一个第三方WindowsForms应用程序编写插件,该插件将与其他插件并存。请注意,我无法控制基础应用程序使用的源代码或文件(如dll文件、配置文件等)或在运行时加载的其他插件。

让我们假设其中一个其他插件在我的插件之前加载,它会加载版本1.0的库A(“A.dll”)。如果我的插件尝试加载版本2.0的库A(也称为“A.dll”),我会立即收到经典的“System.IO.FileLoadException”错误。

在深入了解依赖关系问题之后,我找到了一些选择(例如这里这里)。然而,所有这些选项似乎都集中于独立应用程序,开发人员通常对其拥有完全控制权,需要同时加载两个版本的相同库(可能是为了旧版支持或任何其他奇怪的原因)。由于插件环境的限制,这些解决方案似乎不适用于我的情况。此外,它们经常需要:

  • 向GAC插入程序集,我不知道是否需要最终用户计算机上的管理权限,而我没有这些权限;
  • 控制基础应用程序的配置文件(*.exe.config),我没有这个权限。

请考虑到我所描述的限制,有人可以帮我找到一种使用新版本库的方法吗,该库也被另一个插件作为旧版本使用?

2个回答

0
如果您提供了自己的A.dll 2.0版本库,您可以将其重命名为A.2.0.dll并引用它。

我确实控制着库A.dll,这是我目前的首选方案:简单而有效。但是,为了每个版本都能清晰明了,我需要为该库重命名(为了简化问题,我的库A.dll对应一堆dll文件)。在采用此选项之前,我只想知道是否有其他更优雅的选择来实现这一点。 - Pedro Pinheiro
@PedroPinheiro,由于所有插件都在同一个目录中,而且您无法将任何内容放入GAC中,因此我认为没有其他选择可以让您使用同一文件的多个版本。 - MarTim
1
我们有一个依赖于流行框架如Mono.Cecil的VS扩展,可能会被其他VS扩展加载。在生产环境中,我们确实为一些用户遇到了冲突。我们的解决方案是将其重命名为Mono.Cecil.4NDepend.dll,其中NDepend是我们的产品。最好的后缀方式是使用4YourProduct而不是版本号,这样可以避免重命名第三方,也不会发生版本冲突的情况。 - Patrick from NDepend team
感谢大家的帮助。我已经成功地在我的项目中采用了这个重命名策略,并且可以确认它解决了我最初的问题。 - Pedro Pinheiro

0

您可以处理事件AppDomain.AssemblyResolve以控制使用哪个程序集,具体取决于尝试加载它的程序集。这对我来说似乎是一种欺骗行为,但也许没有干净的方法来解决这个问题。


我同意你的看法,那似乎是个hack。然而,AppDomain.AssemblyResolve应该由应用程序中的每个插件处理,对吧?这可能会带来问题,因为我无法控制应用程序中的其他插件,也不能强制它们使用这种方法...这就是为什么我更倾向于使用像MarTim提出的解决方案,即使它也不是一个理想的解决方案... - Pedro Pinheiro
据我所知,其他程序集与您的程序集位于同一个应用程序域中,因此我认为您是安全的...您只需要确保如果您的插件正在请求程序集(或者如果您的插件版本被请求),则返回正确的程序集。如果您忽略所有其他调用,则应用程序的其余部分将返回默认版本的程序集。 - StefanFFM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接