努格特;传递依赖;绑定重定向地狱

NuGet; Transitive Dependencies; Binding Redirect Hell

.NETCore just litters your disk a lot worse, too many versions, too many assemblies, too many standards and no GAC. Hopefully they'll get their act together sometime soon. – Hans Passant Aug 17 '17 at 10:37

不,它只会越来越糟。 : \


拥有引用 Microsoft 扩展 classes 的 .NET Standard 2.0 class 库。当我们部署到服务器时,我们会得到运行时绑定异常。我的问题首先:

  1. 为什么不为传递依赖生成绑定重定向?
  2. 既然他们不是,我如何想出一个完整的列表来手动添加?
  3. 编译器如何知道要重定向到哪个版本,除非它打算让我部署它编译的版本?
  4. 我如何得出要部署的 DLL 列表 - 不包括框架 DLL,但包括服务器上没有的任何内容?
  5. 如果 \ref\ 中的程序集版本低于 \lib\ 中的程序集版本,是否会破坏 nuget 包?

详情:
我们有一个针对 .NET Standard 2.0 编译的 class 库...它引用 Microsoft.Extensions.Configuration.Json.

MimExtension
 \--Dependendencies
    \--Packages
         \--Microsoft.Extensions.Configuration.Json (5.0.0)
             \--System.Text.Json (5.0.0)
                 \--System.Buffers (4.5.1)

System.Buffers 解析为 \.nuget\packages\system.buffers.5.1\ref\netstandard2.0\System.Buffers.dll。该目录中的文件版本为 4.6.28619.1,日期为 2020/02/19。 .NET Reflector 将程序集版本显示为 4.0.2.0.

该 DLL 的 \lib\ 版本是 \.nuget\packages\system.buffers.5.1\lib\netstandard2.0\System.Buffers.dll...相同的文件版本和日期,但程序集版本是 4.0.3.0

编译 DLL 会给我一个带有绑定重定向的 .dll.config 文件,我可以将其复制到消费应用程序的 app.config - 但 System.Buffers.dllSystem.Text.Json.dll 不是那里。 Microsoft.Extensions.Configuration.Json.dll 也不存在 - 尽管另一个 nuget 包 Microsoft.Extensions.Configuration.Abstractions.dll 存在。

我假设这意味着编译器认为不存在的 DLL 不需要重定向(参见问题 #3)。只有在引用之间存在冲突的 DLL 才会添加到绑定重定向(如果发生这种情况),这是有道理的,但无论是否发生冲突,我们的应用程序都不会绑定到 System.Buffers 的 \lib\ 版本。编译器使用的 dll 和 RTE 的(问题 #1)。

为了解决这个问题,我可以手动添加绑定重定向。但是我如何查看项目中的所有 nuget 引用并确定(递归地)为每个 dll 选择的版本?没有将冗长的构建输出转储到带有一些花哨的正则表达式和一个小时的复制和粘贴的文本文件中,即(问题 #2)。

注意:我可以将 <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> 添加到 .csproj 文件并将 所有 引用的 dll 转储到输出目录 - 包括像 [=25= 这样的 .NET dll ] 和 System.Runtime.CompilerServices.Unsafe.dll- 但这仍然没有让我得到每个版本的完整列表......特别是因为我需要 assembly 版本,我不能甚至在资源管理器中显示。

关于...一些自动生成的绑定重定向是针对 .NET 程序集的,例如 System.Threading...VS 真的希望我部署我编译的 System.Threading 版本吗?对于那个 dll,我有 newVersion="4.0.11.0"... 我们的服务器有程序集版本 4.0.0.0,文件版本 4.8.3761.0。 VS 希望我部署程序集版本 4.0.11.0,文件版本 1.0.24212.01(wtff?!?)。 nuget 下拉的 4.0.11.0 版本日期为 2019/12/26... 4.0.0.0 服务器版本日期为 2021/01/21.

我猜这是核心与框架版本控制 wtf - 但绑定重定向不在乎。将加载我们的库的应用程序是 .NET Framework 4.8...我应该用我的应用程序部署 System.Threading 4.0.11.0 dll,还是手动更改绑定重定向并让它加载服务器的版本?核心 DLL 的程序集版本高于其较新的 .NET Framework 对应版本(问题 #addingnewonesasigo),这绝对是可笑的。

因此,当我们引用 nuget 包时,我们如何知道哪些需要部署,哪些不需要(或更糟,不应该)? (问题 #4)我觉得构建过程应该将 GAC 中不属于 framework/won 的 dll 复制到输出目录 - 但在 nuget 包规范中没有任何 TIAO 表明这一点。

关于#5... nuget 包中的 dll 不应该在 \ref\\lib\ 文件夹中具有相同的版本吗? Microsoft.Extensions.Configuration.Json 中的细分在 System.Text.Json 中...S.T.J 的 .nuspec 列出了对 <dependency id="System.Buffers" version="4.5.1" /> 的 .NET Standard 2.0 依赖项。那么为什么 System.Buffers.dll nuget 缓存在 \ref\\lib\ 中有不同的版本?它们不应该都是 4.0.2.0 或 4.0.3.0 吗?

有很多很多 的问题 - 甚至有些是专门针对 System.Buffers 的。但是没有人为 class 库满意地解决这个问题(我能找到)。我将尝试在解决方案中添加一个临时网站并引用库 - 只是为了看看 .NET 是否获得了必要的 dlls/redirects 到位,因为它唯一的爱:Web

更新
我为 System.Buffers 手动添加了到 4.0.3.0 的绑定重定向...并立即得到了下一个目标:Could not load file or assembly 'System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies

这样下去,直到我们找到一种方法来列出 VS 探测到的所有内容。如果没有 100% 的回归覆盖率,就无法保证我们在部署时不会遗漏任何东西。

对于可执行文件,dotnet publish;并发送生成的文件夹始终正确。

但对于针对 .net 标准编译的 dll;我只成功地构建了一个 nuget 包并引用它并让编译器(其中的整个包)找出项目需要的最终 dll。您可以使用 dotnet pack.

创建一个 nuget 包

我从来不需要绑定重定向到 link .netstandard 到 .net 框架。

为特定平台编译库会将依赖的 DLL 拉入 bin 文件夹。回想起来这是有道理的——为 .NET Standard 编译只有在目标平台未知且库开发人员不会选择时才有意义。这种情况需要一个集中的包管理器。

针对 .NET 4.8(MIM 当前支持的最高版本)为我们提供了 bin 目录中的 DLL 并在配置文件中设置绑定重定向。

也就是说,System.Buffers.DLL 版本问题只是因为正确定义了 .NET 4.8 依赖关系而消失了。 Microsoft.Extensions.Configuration.Json .nuspec 表示与为 .NET Standard 2.0 编译时下载的 dll 不同的程序集版本。我不知道这是 .NET 开发人员编译 nuget 包时引用的问题还是 nuget 打包本身不可避免的产物。