如何使用 Orchard 使用的更新版本的程序集

How to use a newer version of an assembly that Orchard uses

我想在 Orchard CMS 中实现自定义模块。问题是我想引用各种 Orchard CMS 模块使用的库,这些模块引用了这些库的旧版本

我希望我的 plugin/module 能够自我维持 - 我不想要求对 orchard.web 的 web.config 文件进行修改。我希望 运行 orchard 没有源登记的用户能够使用我的模块。

我怎样才能做到这一点? This page 将我自己的模块的 web.config 描述为在绑定重定向方面或多或少没有意义...我尝试只放置这些引用(有问题的库是 System.IdentityModel.Tokens.JwtNewtonsoft.Json ) 在我的模块的 bin 目录中并从那里引用,但是当我尝试安装模块时出现错误:

Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference.

我已经阅读了一些关于 Orchard 的 App_Data/dependencies 文件夹和 orchard.web/bin 文件夹的内容,但我无法理解它们是如何组合在一起的。如何允许我的模块使用新版本的库,同时仍然允许 orchard 模块使用该库的旧(不兼容)版本?

Orchard 很好地给出了一个组合应用程序的错觉,其中只有很少的全局 application-level 实体不能在模块级别被覆盖。然而,程序集加载是其中一个失败的地方。当应用程序被编译和加载时,包括当动态编译进入混合时,所有模块生成和依赖的程序集被收集并复制到全局应用程序的 bin 文件夹中。模块的 bin 文件夹实际上只是从中复制程序集的地方,但实际加载发生在应用程序的 bin 中。所以最后,如果你想知道应用程序到底加载了什么,你需要查看 top-level bin 文件夹。如果您在这里发现错误的版本,是时候进一步挖掘并查看模块有哪些版本,以及它们贡献的顺序。如果我没记错的话,那将取决于它们之间的依赖关系,最外层的依赖关系最后复制它们的程序集,从而获胜。这意味着您可以通过调整清单中的模块依赖顺序来调整它的功能。

第二个全局的东西是程序集绑定配置,因为 ASP.NET 就是这样。有ASP.NET 设置可以在目录级别设置,但是程序集绑定需要发生在顶部,因为应用程序最终只是一个应用程序域,每个程序集只会加载一个副本。当然,这在任何模块化应用程序中都是一个问题,因为模块在编写它们时对其依赖项的版本有不同的期望。 .NET 通过绑定重定向来处理这个问题,这基本上是一种指示运行时假设如果加载特定版本一切都会好的方法。它还会告诉依赖于这些重定向依赖项的程序集一个谎言,因为它假装它们期望的版本存在,但实际上会使用重定向中指定的版本。它经常有效,但并非总是有效(发生重大变化)。如果您重定向到的特定版本实际上不可用,无论是在 GAC 中还是在应用程序的垃圾箱中,它都会失败。

总而言之:

  • 模块无法在其级别上执行任何操作来统一应用程序将使用的程序集版本,它需要在应用程序级别设置绑定重定向。
  • 被重定向到的程序集必须在应用程序的容器中结束。
  • 模块可以在一定程度上影响通过更改其清单中的依赖项顺序将哪些程序集部署到应用程序的容器中(但这需要其他模块的知识)。

当然,理想情况下,所有 third-party 模块以及 Orchard 核心模块都将更新为使用最新版本,但这显然很少见。