首页 文章

为什么我的.NET Standard NuGet包会触发这么多依赖项?

提问于
浏览
28

我一直在与a .NET Standard project和NuGet杂乱无章 . 我有一个工作项目并且uploaded it to NuGet.org . 我的项目面向.NET Standard 1.3,其中包括_6484891_ .NET Framework 4.6和.NET Core 1.0 .

但是当我尝试将我的项目(通过NuGet)添加到一个新的.NET Framework 4.6项目时,依赖项解析为 47 包!它们都是系统库,似乎是Microsoft.NETCore.Platforms或NETStandard.Library 1.6.1的依赖项 . (Gist of full PM output.

我的项目只导入( using )少量库,我没有手动添加;即他们都是_64845 . 这些库是:

  • 系统

  • System.Text

  • System.Reflection

  • System.Linq

  • System.Collections.Generic;

问题是,我决定让我的项目成为.NET Standard,因为我希望它能够跨.NET Framework和.NET Core应用程序无缝地工作 . 我认为标准的重点是设置最低级别的兼容性 . 通过扩展,我想我曾(或许是错误地)假设像System.Console这样的库可以在Core或Framework中自动使用 .

当我在同一个解决方案中测试我的Standard项目作为Framework和Core项目中的依赖项时,我没有注意到这样的事情,所以我怀疑这可能是一个NuGet的事情 .

这里到底发生了什么?如何在没有大量依赖项的情况下在NuGet上提供我的.NET标准库?

这是我指定我的NuGet包的方式有问题吗?或者我从根本上误解了什么?

2 回答

  • 0

    你没有做错任何事,预计会发生这种情况 . 如果您只想将自己的DLL添加到新的.NET Framework项目中,则必须为您的库定位.NET Standard 2.0,等待本机支持API和汇编版本的.NET Framework版本 - 这将是为4.7.2(虽然.NET Framework 4.7.1支持所有API,但有一些程序集的版本化存在错误,因此工具(VS 2017 15.5)将添加其他程序集来修复) .

    您所看到的是.NET Standard的构建方式以及对支持的框架的支持的副作用 . 根据您定位的.NET Standard版本和用于引用库包的工具,这也有所不同 .

    在.NET Standard <2.0中,您引用了 NETStandard.Library 元数据包,后者又引用了其他( System.* )包 . 这些包包含构成".NET Standard Contract"的引用程序集 - 一组API和程序集名称版本 .

    当您为.NET Standard 1.0-1.6创建的NuGet包随后被应用程序引用时,这些单独的包不会引入引用程序集,而是引入应用程序所针对的框架的实现程序集 .

    对于.NET Core,它们匹配已经属于运行时的程序集,因此DLL文件不会在构建的应用程序旁边结束 . 但是,当为.NET Core 1.1( NETStandard.Library 版本1.6.1)发布一组新的软件包时,这发生了变化 . 这导致为.NET Core 1.0构建的应用程序最终获得了旨在包含在.NET Core 1.1中的更新的实现程序集(幸运的是,1.1因此成为"long-term support"版本,因为这引发了关于哪些程序集是LTS的一部分的讨论诺言) .

    在.NET Framework上,这些库(有一些例外,如 System.Net.Http )没有做太多 - 它们只是转发到系统程序集 . 例如,"contract"定义 System.ObjectSystem.Runtime.dll 程序集中定义 . 因此,您在.NET Framework应用程序中最终得到的 System.Runtime.dll 文件包含 System.Runtime.dll ,其中包含转发到.NET Framework的 mscorlib.dll 类型 . .NET Core已经包含一个不同的 System.Runtime.dll ,它为该平台做了不同的事情 . 此机制允许单个DLL文件在两个平台上都可以工作,因为这些类型转发和其他实现可确保在两个实现上使用相同的"contract"(类型程序集程序集版本) .

    .NET Standard 2.0旨在减少必需的包和DLL的数量,并且每当发布新的.NET Core版本时,都要删除对 NETStandard.Library 的更新 .

    因此,对于.NET Standard 2.0和.NET Core 2.0, NETStandard.Library 包只会将用于编译代码的引用程序集带到项目中,但生成的NuGet程序包不再依赖于此程序包 . 因此,当您创建一个面向.NET Standard 2.0并发布它的库时,它将没有NuGet依赖项(除非您添加其他的) .

    使用.NET标准库时引入的内容的逻辑被移动到构建期间使用的工具 . 因此,当包含对 netstandard.dll 的引用的库添加到.NET Framework项目时,工具将添加基于的必要支持DLL正在使用的.NET Framework版本 . 这是针对.NET Standard 2.0以及.NET Standard 1.5完成的,因为.NET Framework 4.6.1通过这些类型的DLL文件追溯性地与.NET Standard 2.0(先前为1.4)兼容 . 相同的工具还确保即使NuGet包以某种方式引入到这样的应用程序项目中,从构建中删除通过NuGet引入的任何.NET标准实现库 . 因此,如果您引用.NET Core 1.0发布时构建的.NET Standard 1.0 NuGet包,则会修剪其所有NuGet依赖项,并获得构建工具附带的支持库 .

    想法是.NET Framework 4.7.1将包含所有必需的程序集"inbox",以便_648415_, System.Runtime.dll 等是.NET Framework的一部分,任何.NET Standard 1.0-2.0 DLL文件都会"just work",问题是这些"inbox" dll文件的某些程序集的版本号太低,因此库无法加载 - 这是通过再次更改工具以包含具有更高版本号的DLL文件作为支持库来修复的,而这些文件又转发到"inbox" .NET Framework程序集 . 计划在.NET Framework 4.7.2中修复此问题 .

  • 39

    我也遇到了这个问题 . 您在对Martin Ullrich的回答中发表评论的blog post让我找到了一个对我有用的解决方案:使用NuGet multi-targeting . 通过更改:

    <TargetFramework>netstandard1.0</TargetFramework>
    

    <TargetFrameworks>netstandard1.0;netstandard2.0;net45</TargetFrameworks>
    

    在项目 .csproj 文件中 . 这会导致为每个目标框架单独构建项目,并且生成的NuGet包仅依赖于 NETStandard.Library for netstandard1.0 . 从NuGet chooses the net45 binaries for any full .NET Framework version开始,这可以避免在安装软件包时出现不必要的依赖关系 .

相关问题