【问题标题】:When do I have to use binding redirects?我什么时候必须使用绑定重定向?
【发布时间】:2015-04-18 12:27:51
【问题描述】:

项目 A 使用 log4net 1.2.13.0,并依赖于使用 log4net 1.2.11.0 的库 B。如果我这样做Package Manager Console> Add-BindingRedirect,我会在app.config 中获得正确的绑定重定向:

  <dependentAssembly>
    <assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-1.2.13.0" newVersion="1.2.13.0" />
  </dependentAssembly>

我认为这是必需才能完成构建。但是在没有重定向的情况下构建也会成功。这是我在构建日志中看到的(详细设置为详细):

统一主要参考“log4net, Version=1.2.13.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a”。 在“C:\Users\vorou\code\ConsoleApplication1\packages\LibraryB.dll”中使用此版本而不是原始版本“1.2.11.0”,因为 AutoUnify 为“true”。

AutoUnify 是关于什么的?哪个更好,即在 .config 中进行显式重定向有什么好处?

另外,我记得,在某些情况下,您需要添加绑定重定向。否则应用程序将在运行时崩溃。这些情况是什么?为什么AutoUnify 魔法对他们不起作用?


UPD这是MSDN关于AutoUnify的摘录:

此参数用于构建程序集,例如 DLL,这些程序集不能具有正常的 App.Config 文件。 当为 true 时,生成的依赖关系图会自动被视为有一个 App.Config 文件传递​​给 AppConfigFile 参数。此虚拟 App.Config 文件对于每个冲突的程序集集都有一个 bindingRedirect 条目,以便选择最高版本的程序集。这样做的结果是永远不会有关于冲突程序集的警告,因为每个冲突都将得到解决。

在我的情况下,.config 中的重定向似乎没有任何作用。问题是库 B 不能满足它的依赖关系,AutoUnify 用“假装存在绑定重定向”规则解决了它。

【问题讨论】:

    标签: .net msbuild nuget


    【解决方案1】:

    版本控制是一个大话题,不能在单个 SO 帖子中做到公正。如此惊人的速度:

    当您使用多个 Nuget 包并且它们具有共同的依赖关系时,这些恶作剧是必要的。像 log4net 或 NewtonSoft.Json,非常常见的库,它们没有将程序集放入 GAC 的安装程序。

    问题是,每个 Nuget 包很可能使用不同版本的这些核心支持库构建。而且这样的包不太可能获得足够的更新来保持最新版本,包作者更喜欢他测试代码的版本。因此,您将很容易在构建目录中得到一个要求 1.2.11.0 的程序集和另一个要求 1.2.13.0 的程序集

    那是行不通的。 CLR 在加载程序集时坚持 exact 版本匹配。并且必须从您的构建目录中加载它,并且不能依赖 GAC 来提供它们。 DLL 只能有一份副本,不可避免地,其中一个包库会得到错误的版本,您的程序会崩溃。不好,你有一个不重建 Nuget 包就无法解决的问题。

    这就是绑定重定向解决的问题。它只在运行时产生影响,而不是在构建时产生影响。它告诉 CLR,“如果它要求 1.2.11.0,那么只需加载 1.2.13.0。或者更一般地说,使用这个特定的绑定重定向:“如果它要求 any 版本小于 1.2.13.0” . 问题解决了,没有崩溃了。手指交叉,包仍然适用于新版本。当只有修订号不同时,他们很常见。但没有硬性保证。

    另一件需要决定的事情,这发生在构建时,是应该选择哪个特定版本的库。你想要 1.2.11.0 还是 1.2.13.0?这就是 AutoUnify 所做的。没有什么很复杂的,它会选择更高的版本。

    【讨论】:

    • 如果我们有 A -> C(v2.1) 和 B -> C(v2.2) 为什么不将 A 和 B 的依赖关系视为自己的业务? (因为 CLR 等......)但为什么 CLR 又要强制这样的约束呢?谢谢!
    • CLR 没有这样的约束。您有两个名为 C.dll 的文件,您只能将它们放在一个位置,这样它们就不会相互覆盖。不要使用它。
    • 我在这里缺乏知识,但为什么需要将 C 暴露在 A 和 B 之外。A 和 B 应该是独立/自包含的 dll。 (我不是在争论只是想更好地理解“为什么”)。感谢您的耐心等待
    • 绝对不能保证您的软件在使用该依赖项的最新版本 (1.2.13.0) 时不会崩溃,因为库 B 专门使用版本 1.2.11.0 进行了测试。正如汉斯所说:“手指交叉,该软件包仍然适用于较新的版本。” - 这意味着您在自己的同意和风险下接受该版本冲突解决方案。 +1
    猜你喜欢
    • 2011-10-23
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 2016-10-22
    • 2020-03-06
    • 2014-11-08
    • 2013-10-23
    • 2014-04-26
    相关资源
    最近更新 更多