绑定重定向在 VSPackage/VSIX 中无效

Binding redirect not effective in VSPackage/VSIX

主要问题

我正在使用 VS2017 (15.9.25) 开发 VSIX VSPackage。

该包使用 MySqlConnector 1.0.0 NuGet 包,后者又依赖于包含 System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51 程序集的 System.Memory 4.5.4 NuGet 包。

当我 运行 我的 VSPackage 在调试模式下使用 Visual Studio 实验实例时,我的插件加载,我可以看到我的自定义选项页面和我添加到的自定义命令VS 上下文菜单。但是当我实际上 运行 自定义命令(它试图使用 MySqlConnector 检索一些数据)时,数据库连接失败,因为 System.Memory 程序集失败加载。

在异常消息中提供了一些我不完全理解的更多调试信息:

我的 app.config 包含以下绑定重定向:

  <dependentAssembly>
    <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
  </dependentAssembly>

bin/Debug文件夹和生成的.vsix文件都包含MySqlConnector.dll 1.0.0System.Memory.dll 4.0.1.1

使用 ReSharper 的程序集资源管理器查看 MySqlConnector.dll,我看到它引用了 System.Memory 4.0.1.0,这是无法加载的程序集。

我的问题是:

  1. 为什么 FileNotFoundException 提到 4.0.1.0?绑定重定向不应该导致 .NET 尝试加载 4.0.1.1,它确实存在吗?
  2. 在 VSIX/VSPackage 上下文中配置绑定重定向需要我做什么特别的事情吗?
  3. 额外的程序集 binding/loading 诊断(例如 === Pre-bind state information === 等)究竟意味着什么?
  4. 我需要更改什么才能正确加载此程序集?

更多详情

我从标准的 VS2017 VSIX 包项目模板开始,它以 .NET 4.6 为目标,后来将我的项目重新定位到 .NET Framework 4.7.2。

我认为问题可能是由 .NET Fx 4.7.2 中包含但在针对 .NET Fx 4.6 时单独提供的类型引起的,因此我尝试重新安装 MySqlConnectorSystem.Memory 将目标更改为 4.7.2 后的 NuGet 包。没有区别。

我正在使用传统的 packages.config 风格的 NuGet 配置。

VSIX 包使用 NuGet 包 MySqlConnector 1.0.0 (project home page)。该包没有明确列出任何 .NET 4.7.2 的依赖项:

.NETFramework,Version=4.7.1 的依赖项似乎也适用于 4.7.2,因为安装 MySqlConnector 会导致 System.Memory 4.5.4 NuGet 包也被安装。这会将对 System.Memory 4.0.1.1 程序集的引用添加到我的 VSIX VSPackage 项目,其中 Copy Local == True:

选中项目属性中“自动生成绑定重定向”的复选框:

但是,奇怪的是,csproj 文件中没有 <AutoGenerateBindingRedirects> 元素。也许该元素由于某种原因不适用于 VSIX 项目,或者它在某些时候变成了隐式行为?

当我构建我的项目时,System.Memory.dll 文件正从 NuGet 包文件夹复制到二进制输出文件夹,正如我所期望的那样:

使用ILSpy检查二进制输出文件夹中的文件证明它是最新版本,并且匹配app.config中的程序集绑定重定向:

// C:\git\[redacted]\bin\Debug\System.Memory.dll
// System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// Global type: <Module>
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly is signed with a strong name key.
// Hash algorithm: SHA1

使用 7-zip 打开输出文件夹中的 .vsix 文件显示 VSIX 还包含 System.Memory.dll:

似乎答案是 .NET 试图加载旧版本,因为 VSPackage/VSIX 项目 (由 NuGet 包 install/uninstall 操作维护),因为它们是在 Visual Studio 的 devenv.exe 的上下文中加载的插件,它从自己的 devenv.exe.config VSIX 无法编辑的文件中获取其主要绑定重定向配置。

相反,VSIX 基础结构允许在 .pkgdef 文件中配置绑定重定向,VS 在加载 VSPackage 时会注意这些文件。 .pkgdef 文件是 VSIX 构建过程的输出,因此直接编辑它会相当脆弱。维护 .pkgdef 绑定重定向的最简单方法是将 Microsoft.VisualStudio.Shell.ProvideBindingRedirectAttribute 的 assembly-scoped 个实例添加到 VSPackage 项目的 AssemblyInfo.cs 文件中。 VSIX 构建工具将选取这些属性并在构建 VSIX 时在 .pkgdef 文件中生成绑定重定向。

根据我的 app.config 的内容添加各种 ProvideBindingRedirectAttribute 实例后,我现在可以加载 MySqlConnector DLL。