为什么程序集加载器在绑定重定向后无法匹配 dll 版本?

Why is assembly loader failing to match dll revision after binding redirect?

有很多关于绑定重定向的 SO 问题,但是 none 解释了为什么程序集加载器可能无法匹配看起来很像的 dll 的修订 should匹配。

我的项目在运行时失败,显示“无法加载文件或程序集”。内部异常的FusionLog属性是这样写的:

=== Pre-bind state information ===
LOG: DisplayName = Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
 (Fully-specified)
LOG: Appbase = file:///D:/work/code/b6/Backend/CSharp/Applications/Web/Ingestion/Backend/csx/Debug/roles/WorkerRole1/approot
LOG: Initial PrivatePath = D:\work\code\b6\Backend\CSharp\Applications\Web\Ingestion\Backend\csx\Debug\roles\WorkerRole1\approot
Calling assembly : Microsoft.Azure.Cosmos.Table, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\work\code\b6\Backend\CSharp\Applications\Web\Ingestion\Backend\csx\Debug\roles\WorkerRole1\approot\WorkerRole1.dll.config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 10.0.0.0 redirected to 11.0.1.21818.
LOG: Post-policy reference: Newtonsoft.Json, Version=11.0.1.21818, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: Attempting download of new URL file:///D:/work/code/b6/Backend/CSharp/Applications/Web/Ingestion/Backend/csx/Debug/roles/WorkerRole1/approot/Newtonsoft.Json.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

这些行

LOG: Redirect found in application configuration file: 10.0.0.0 redirected to 11.0.1.21818
...
file:///D:/work/code/b6/Backend/CSharp/Applications/Web/Ingestion/Backend/csx/Debug/roles/WorkerRole1/approot/Newtonsoft.Json.DLL

表示正在应用我设置的绑定并且加载程序正在检查预期的 dll。

查看 dll 属性(从该路径)我发现版本与重定向相匹配...

但我仍然遇到这种不匹配

WRN: Comparing the assembly name resulted in the mismatch: Revision Number

我还使用 sn 工具验证了 PublicKeyToken 符合预期。

任何人都可以建议这里可能发生的事情吗?我能想到的是 FusionLog 输出是 incorrect/incomplete 并且实际上正在检查一个不同的 dll。

不确定您在 app.config 文件下对 bindredirect 做了什么。我想你错过了程序集版本、文件版本和产品版本。

BindRedirect 使用程序集版本而不是您显示的产品版本和文件版本。参见 this document

产品版本文件版本用于产品的对外发布,用于展示产品的特性,是只是一个外部描述。

但是,Assembly Version用于特定的内部用途,如dll解析、引用、加载、绑定,那么我们使用汇编版本。并且注意版本号是无法从外部访问到的,我们只能在比如vs ide解析的时候才能看到。

在你的问题中,Newtonsoft.Json 11.0.1 nuget 包,

其dll的文件版本为11.0.1.21818,产品版本为11.0.1,程序集版本为11.0.0.0

因此您应该检查 csproj 文件并更改为使用汇编版本:

 <Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=xxx, processorArchitecture=MSIL">
      <HintPath>..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
 </Reference>

如果您在 app.config 文件下使用了 bindredirect,请使用:

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      ........
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="xxx" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
      </dependentAssembly>

    </assemblyBinding>
  </runtime>