NuGet;传递依赖;绑定重定向地狱

问题描述

.NETCore 只会让你的磁盘变得更糟,版本太多,程序集太多,标准太多,而且没有 GAC。希望他们能尽快采取行动。 – Hans Passant 2017 年 8 月 17 日 10:37

不,它只会变得更糟。 :\


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

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

详情:
我们有一个针对 .NET Standard 2.0 编译的类库……它引用了 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\4.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\4.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.dll 的 \lib\ 版本编译器使用和 RTE(问题 #1)。

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

注意:我可以将 <copyLocalLockFileAssemblies>true</copyLocalLockFileAssemblies> 添加到 .csproj 文件并将 all 引用的 dll 转储到输出目录 - 包括 .NET dll,如 System.Threading.dll 和 {{1 }}- 但这仍然没有让我得到每个版本的完整列表......特别是因为我需要 assembly 版本,我什至无法在资源管理器中显示

关于……一些自动生成的绑定重定向是针对 .NET 程序集的,比如 System.Runtime.CompilerServices.Unsafe.dll……VS 真的希望我部署我编译的 System.Threading 版本吗?对于那个 dll,我有 System.Threading...我们的服务器有程序集版本 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。

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

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

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

有很多关于此的很多问题 - 甚至有些是专门针对 System.Buffers 的。但是没有人为类库满意地解决了这个问题(我可以找到)。我将尝试在解决方案中添加一个临时网站并引用该库 - 只是为了看看 .NET 是否为其唯一的爱获得了必要的 dll/重定向:Web

更新
我为 System.Buffers 手动添加一个到 4.0.3.0 的绑定重定向......并立即得到了下一个鼹鼠:\lib\

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

解决方法

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

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

我从来不需要绑定重定向来将 .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 包本身不可避免的工件。