2017-11-18 276 views
6

我一直在使用a .NET Standard project和NuGet。我有一个工作项目,并有uploaded it to NuGet.org。我的项目面向.NET Standard 1.3,其中包括.NET Framework 4.6和.NET Core 1.0。为什么我的.NET Standard NuGet包会触发如此多的依赖关系?

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

我的项目只进口(using)一些库,我没有手动添加;即它们都是“附带”.NET标准的库。这些库是:

  1. 系统
  2. System.Text
  3. 的System.Reflection
  4. System.Linq的
  5. System.Collections.Generic;

的事情是,我决定把我的项目目标.NET标准,因为我想它跨越.NET Framework和.NET核心应用无缝协作。我认为标准的全部内容是设定兼容性的最低水平。通过扩展,我想我假定(也许是错误的)像System.Console这样的库可以在Core或Framework中自动获得。

当我在同一解决方案中将我的标准项目作为Framework和Core项目中的依赖项进行测试时,我没有注意到任何此类事情,所以我很怀疑这可能是NuGet的事情。

这里究竟发生了什么?我怎样才能让我的.NET标准库在NuGet上可用,而不需要大量的依赖关系?

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

+0

您是否注意到是否有任何内容实际添加到输出文件夹中,或者在安装软件包时它是否只是一个可怕的依赖列表?我的经验是它是后者,这仍然不是很好,但不是令人担忧。 –

+0

@JonSkeet我的软件包文件夹里现在有一长串文件夹,当时我真的只想到一个文件夹。另外,“管理NuGet包”屏幕显示所有包(其中一些包含未决更新)。 –

+2

正确 - 但bin目录中有什么? (FWIW,我完全同意这是一个非常不幸的情况。我不知道它是否在以后的版本中有所改进。但这就是为什么对于我生产的一些软件包,我创建了net45目标以及netstandard1.x版本......) –

回答

9

你没有做错任何事,预计会发生。如果您只想将自己的DLL添加到新的.NET Framework项目中,则必须将.NET Standard 2.0作为您的库的等待.NET Framework版本,该版本本身支持API和程序集版本 - 这会进行为4.7.2(虽然.NET Framework 4.7.1支持所有的API,但是有些程序集是如何版本化的,所以工具(VS 2017 15.5+)会添加额外的程序集来解决这个问题)。

您所看到的是.NET Standard如何构建以及对支持的框架的支持是如何实现的副作用。基于您的目标.NET标准版本和用于引用库软件包的工具,这也是不同的。

在.NET标准< 2.0中,您引用了NETStandard.Library元程序包,该元程序包又引用了其他(System.*)程序包。这些软件包包含构成“.NET标准合同”的引用程序集 - 一组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因此而成为“长期支持”版本,因为这引发了关于哪些程序集是LTS承诺的一部分)。

在.NET Framework上,这些库(有一些例外如System.Net.Http)做的不多 - 它们只是转发给系统组件。因此,例如“合同”定义System.ObjectSystem.Runtime.dll组件中定义。因此,最终在.NET Framework应用程序中使用的System.Runtime.dll文件包含System.Runtime.dll,其中包含向.NET Framework的mscorlib.dll转发的类型。 .NET Core已经包含了一个不同的System.Runtime.dll,它为该平台做了一些不同的事情。这种机制允许单个DLL文件在两个平台上工作,因为这些类型的转发和附加实现确保在两个实现上工作的“契约”(类型+程序集+程序集版本)相同。

.NET标准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项目时,工具将根据所使用的.NET Framework版本添加必要的支持DLL。这是针对.NET标准2.0以及.NET标准1.5+完成的,因为.NET Framework 4.6.1通过这些类型的DLL文件追溯地与.NET标准2.0(以前是1.4)兼容。同样的工具也确保即使NuGet包以某种方式被引入到这样的应用程序项目中,通过NuGet引入的任何.NET标准实现库都将从构建中移除。因此,如果您参考.NET Core 1.0发布时构建的.NET Standard 1.0 NuGet包,则它的所有NuGet依赖关系都将被修剪掉,您将获得构建工具附带的支持库。

这个想法是,.NET Framework 4.7.1将包含所有必要的程序集“收件箱”,以便netstandard.dllSystem.Runtime.dll等等是.NET Framework的一部分,任何.NET Standard 1.0-2.0 DLL文件都将“只是工作“,问题在于这些”收件箱“dll文件的版本号对于某些程序集来说太低,所以程序库将无法加载 - 通过再次更改工具以包含具有更高版本号的DLL文件作为支持库转向“收件箱”.NET Framework程序集。这计划在.NET Framework 4.7.2中修复。

+0

谢谢马丁。花了我一段时间来充分消化这个非常全面的答案。我想.NET标准仍然处于初级阶段,这是最大的难题之一。我会坐下来等待Framework的4.7.2版本。 –

+0

我的注意力已被吸引到一种解决方法:http://blog.tdwright.co.uk/2017/11/21/update-getting-net-standard-apps-playing-nicely-on-nuget/ –

+1

是的,NuGet的在考虑别人之前,get-nearest-framework逻辑更倾向于使用较低版本的相同目标框架(所以'net471'项目甚至会选择'net35' over'netstandard2.0') –

相关问题