问题描述
我一直在纠结一个.NET Standard 项目 和 NuGet.我有一个工作项目,并已 将其上传到 NuGet.org.我的项目针对 .NET Standard 1.3,应该支持 .NET框架 4.6 和 .NET Core 1.0.
I've been mucking about with a .NET Standard project and NuGet. I've got a working project and have uploaded it to NuGet.org. My project targets .NET Standard 1.3, which should support .NET Framework 4.6 and .NET Core 1.0.
但是当我尝试将我的项目(通过 NuGet)添加到新的 .NET Framework 4.6 项目时,依赖项解析为 47 个包!它们都是系统库,并且似乎是 Microsoft.NETCore.Platforms 或 NETStandard.Library 1.6.1 的依赖项.(完整 PM 输出的要点.)
But when I tried to add my project (via NuGet) to a fresh .NET Framework 4.6 project, the dependencies resolved to 47 packages! They're all system libraries and appear to be dependencies of either Microsoft.NETCore.Platforms or NETStandard.Library 1.6.1. (Gist of full PM output.)
我的项目只导入(使用
)少数库,我没有手动添加;即它们都是附带".NET Standard 的库.这些库是:
My project only imports (using
) a handful of libraries, none of which I added manually; i.e. they're all libraries that "came with" .NET Standard. These libraries are:
- 系统
- 系统文本
- 系统.反射
- System.Linq
- System.Collections.Generic;
问题是,我决定让我的项目以 .NET Standard 为目标,因为我希望它能够在 .NET Framework 和 .NET Core 应用程序之间无缝工作.我认为标准的重点是设置最低级别的兼容性.通过扩展,我想我已经假设(可能是错误地)像 System.Console 这样的库将自动在 Core 或 Framework 中可用.
The thing is, I decided to make my project target .NET Standard because I wanted it to work seamlessly across .NET Framework and .NET Core applications. I thought the whole point of Standard was to set a minimum level of compatibility. By extension, I suppose I had assumed (perhaps erroneously) that libraries like System.Console would be automatically available in either Core or Framework.
当我在同一个解决方案中测试我的标准项目作为框架和核心项目中的依赖项时,我没有注意到类似的事情,所以我怀疑这可能是 NuGet 的事情.
I didn't notice anything like this when I tested my Standard project as a dependency in a Framework and Core project within the same solution, so I'm suspicious that this might be a NuGet thing.
这里到底发生了什么?以及如何在没有大量依赖项列表的情况下使我的 .NET Standard 库在 NuGet 上可用?
What's really going on here? And how can I make my .NET Standard library available on NuGet without a huge list of dependencies?
我指定 NuGet 包的方式有问题吗?还是我从根本上误解了什么?
Is it a problem with the way I've specified my NuGet package? Or have I fundamentally misunderstood something?
推荐答案
你没有做错什么,这是预料之中的.如果您只想将自己的 DLL 添加到新的 .NET Framework 项目中,则必须针对库的 .NET Standard 2.0 等待原生支持 API 和程序集版本的 .NET Framework 版本——这将是为 4.7.2(虽然 .NET Framework 4.7.1 支持所有 API,但某些程序集的版本控制方式存在错误,因此工具(VS 2017 15.5+)将添加额外的程序集来修复该问题).
You haven't done anything wrong, this is expected to happen. If you want nothing more than your own DLL being added to a new .NET Framework project, you have to target .NET Standard 2.0 for your library wait for a .NET Framework version that natively supports both the API and assembly versions - which is going to be 4.7.2 (while .NET Framework 4.7.1 supports all the APIs, there were bugs with how some assemblies are versioned and so the tooling (VS 2017 15.5+) will add additional assemblies to fix that).
您看到的是如何构建 .NET Standard 以及实现对受支持框架的支持的副作用.这也因您面向的 .NET Standard 版本和用于引用库包的工具而异.
What you are seeing are side effects of how .NET Standard is built and the support for the supported frameworks is implemented. This is also different based on the .NET Standard version you target and the tooling used to reference the library package.
在 .NET 标准中
在 2.0 中,您引用了 NETStandard.Library
元包,该元包又引用了其他 (System.*
) 包.这些包包含构成.NET 标准合同"的参考程序集 - 一组 API 和程序集名称 + 版本.
In .NET Standard < 2.0, you reference the NETStandard.Library
meta-package which in turn references additional (System.*
) packages. Those packages contain the reference assemblies that make up the ".NET Standard Contract" - a set of APIs and the assembly names + versions.
当您为 .NET Standard 1.0-1.6 创建的 NuGet 包随后被应用程序引用时,这些单独的包不会引入引用程序集,而是引入应用程序所针对的框架的实现程序集.
When the NuGet package you create for .NET Standard 1.0-1.6 is then referenced by an application, these individual packages don't bring in the reference assemblies but rather implementation assemblies for the framework that the application targets.
对于 .NET Core,这些匹配已经是运行时一部分的程序集,因此 DLL 文件不会在生成的应用程序旁边结束.然而,当为 .NET Core 1.1(NETStandard.Library
1.6.1 版)发布了一组新的包时,这种情况发生了变化.这导致为 .NET Core 1.0 构建的应用程序最终获得了本应包含在 .NET Core 1.1 中的更新的实现程序集(幸运的是,1.1 随后成为长期支持"版本,因为这引发了关于哪些程序集的讨论是 LTS 承诺的一部分).
For .NET Core, these match the assemblies that are already part of the runtime so the DLL files won't end up next to the built application. This changed however when a new set of packages was released for .NET Core 1.1 (NETStandard.Library
version 1.6.1). This resulted in applications built for .NET Core 1.0 ending up getting newer implementation assemblies that were meant to be included in .NET Core 1.1 (luckily, 1.1 was then made the "long-term support" version since that sparked a discussion about which assemblies are part of the LTS promise).
在 .NET Framework 上,这些库(有一些例外,如 System.Net.Http
)并没有做太多的事情 - 它们只是转发到系统程序集.例如,合同"定义 System.Object
在 System.Runtime.dll
程序集中定义.因此,您最终在 .NET Framework 应用程序中得到的 System.Runtime.dll
文件包含一个 System.Runtime.dll
,其中包含转发到 .NET Framework 的 的类型mscorlib.dll
..NET Core 已经包含一个不同的 System.Runtime.dll
,它为该平台执行不同的操作.这种机制允许单个 DLL 文件在两个平台上工作,因为这些类型转发和附加实现确保在两个实现上工作的相同合同"(类型 + 程序集 + 程序集版本).
On .NET Framework these libraries (with some exceptions like System.Net.Http
) don't do much - they just forward to the system assemblies. So for example the "contract" defines that System.Object
is defined in a System.Runtime.dll
assembly. So the System.Runtime.dll
file you end up with in a .NET Framework application contains a System.Runtime.dll
that contains type forward to .NET Framework's mscorlib.dll
. .NET Core already contains a different System.Runtime.dll
that does something different for that platform. This mechanism allows for a single DLL file to work on both platforms since those type forwards and additional implementations assure the same "contract" (types + assemblies + assembly versions) working on both implementations.
.NET Standard 2.0 旨在减少所需的包和 DLL 的数量,并在发布新的 .NET Core 版本时删除对 NETStandard.Library
的要求更新.
.NET Standard 2.0 aimed to reduce the number of packages and DLLs being necessary and also to remove requiring updates to NETStandard.Library
whenever a new .NET Core version is released.
因此对于 .NET Standard 2.0 和 .NET Core 2.0,NETStandard.Library
包仅将用于编译代码的参考程序集引入项目,但生成的 NuGet 包不再依赖于该包.因此,当您创建一个面向 .NET Standard 2.0 的库并发布它时,它将没有 NuGet 依赖项(除非您添加其他依赖项).
So for .NET Standard 2.0 and .NET Core 2.0, the NETStandard.Library
package only brings reference assemblies for compiling code to a project, but the resulting NuGet package no longer depends on this package. So when you create a library targeting .NET Standard 2.0 and publish it, it will have no NuGet dependencies (unless you add additional ones).
使用 .NET Standard 库时引入的支持库"逻辑已移至构建期间使用的工具.因此,当将包含对 netstandard.dll
引用的库添加到 .NET Framework 项目时,该工具将根据所使用的 .NET Framework 版本添加必要的支持 DLL.这是为 .NET Standard 2.0 和 .NET Standard 1.5+ 完成的,因为 .NET Framework 4.6.1 通过这些类型的 DLL 文件追溯地与 .NET Standard 2.0(之前是 1.4)兼容.相同的工具还确保即使 NuGet 包以某种方式引入此类应用程序项目,通过 NuGet 引入的任何 .NET Standard 实现库也会从构建中删除.因此,如果您引用了在 .NET Core 1.0 发布时构建的 .NET Standard 1.0 NuGet 包,它的所有 NuGet 依赖项都将被删除,而您将获得随构建工具一起提供的支持库.
The logic of what "support libraries" to bring in when consuming a .NET Standard library was moved to the tooling that is used during build. So when a library that contains a reference to a netstandard.dll
is added to a .NET Framework project, the tooling will then add necessary support DLLs based on the version of .NET Framework being used. This was done for .NET Standard 2.0 as well as .NET Standard 1.5+ since .NET Framework 4.6.1 was retroactively made compatible with .NET Standard 2.0 (was 1.4 previously) through these kinds of DLL files. The same tooling also makes sure that even if NuGet packages are somehow brought in to such an application project, any .NET Standard implementation libraries brought in via NuGet are removed from the build. So if you reference a .NET Standard 1.0 NuGet package that was built when .NET Core 1.0 was released, all its NuGet dependencies are trimmed out and you get the support libraries shipped with the build tooling instead.
这个想法是 .NET Framework 4.7.1 将包含所有必要的程序集收件箱",以便 netstandard.dll
、System.Runtime.dll
等.是 .NET Framework 的一部分,任何 .NET Standard 1.0-2.0 DLL 文件都可以正常工作",问题是这些收件箱"dll 文件对于某些程序集的版本号太低,因此库将无法加载 - 这是通过再次更改工具以包含具有更高版本号的 DLL 文件作为支持库来修复,这些支持库又转发到收件箱".NET Framework 程序集.计划在 .NET Framework 4.7.2 中修复此问题.
The idea was that .NET Framework 4.7.1 would contain all the necessary assemblies "inbox" so that a netstandard.dll
, System.Runtime.dll
etc. are part of .NET Framework and any .NET Standard 1.0-2.0 DLL file would "just work", the problem was that these "inbox" dll files had a too low version number for some assemblies so libraries would fail to load - this was fixed by changing the tooling again to include DLL files with higher version numbers as support libraries which in turn forward to the "inbox" .NET Framework assemblies. This is planned to be fixed in .NET Framework 4.7.2.
这篇关于为什么我的 .NET Standard NuGet 包会触发如此多的依赖项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!