绑定重定向在VSPackage / VSIX中无效 主要问题更多详细信息

问题描述

主要问题

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

该程序包使用MysqLConnector 1.0.0 NuGet程序包,而该程序包又依赖于system.memory 4.5.4 NuGet程序包,其中包括system.memory,Version=4.0.1.1,Culture=neutral,PublicKeyToken=cc7b13ffcd2ddd51程序集。

当我使用Visual Studio实验实例在调试模式下运行VSPackage时,将加载我的插件,并且可以看到我的自定义选项页面和要添加到VS上下文菜单自定义命令。但是当我实际上运行自定义命令(尝试使用MysqLConnector检索某些数据)时,数据库连接失败,因为system.memory程序集无法加载。

FileNotFoundException details

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

additional assembly loading details

我的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的Assembly Explorer查看MysqLConnector.dll,我看到它引用了system.memory 4.0.1.0,这是无法加载的程序集。

我的问题是:

  1. 为什么FileNotFoundException提到4.0.1.0?绑定重定向不应该导致.NET尝试加载肯定存在的4.0.1.1吗?
  2. 在VSIX / VSPackage上下文中配置绑定重定向是否需要做些特别的事情?
  3. 额外的程序集绑定/加载诊断程序(例如=== Pre-bind state @R_94_4045@ion ===等)实际上是什么意思?
  4. 要使此程序集正确加载,我需要更改什么?

更多详细信息

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

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

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

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

MySqlConnector dependency list from NuGet package manager

但是似乎.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程序集的引用:

System.Memory reference properties

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

auto-generate binding redirects is checked

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

在构建项目时,正如我期望的那样,system.memory.dll文件已从NuGet包文件夹复制到二进制输出文件夹中:

Windows explorer screencap showing System.Memory.dll in output folder

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

// C:\git\[redacted]\bin\Debug\system.memory.dll
// system.memory,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

VSIX archive contents

解决方法

似乎答案是.NET试图加载旧版本,因为VSPackage / VSIX项目do not honor binding redirects configured in app.config(由NuGet软件包安装/卸载操作维护),因为它们是在上下文中加载的插件是Visual Studio的devenv.exe的一部分,它从自己的devenv.exe.config文件中获取了VSIX无法编辑的主要绑定重定向配置。

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

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