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

2024-03-25

我一直在闲逛.NET 标准项目 https://github.com/tdwright/contabs和 NuGet。我有一个工作项目并且有已将其上传到 NuGet.org https://www.nuget.org/packages/ConTabs.tdwright/0.1.0。我的项目面向 .NET Standard 1.3,其中应该支持 https://learn.microsoft.com/en-us/dotnet/standard/net-standard.NET Framework 4.6 和 .NET Core 1.0。

但是,当我尝试将我的项目(通过 NuGet)添加到新的 .NET Framework 4.6 项目时,依赖关系解析为47包!它们都是系统库,并且似乎是 Microsoft.NETCore.Platforms 或 NETStandard.Library 1.6.1 的依赖项。 (完整 PM 输出的要点。 https://gist.github.com/tdwright/0b3568a9da2e318fe6e3c2efc40fcff4)

我的项目仅导入(using)一些库,其中没有一个是我手动添加的;即它们都是“附带”.NET Standard 的库。这些库是:

  1. System
  2. 系统.文本
  3. 系统.反射
  4. 系统Linq
  5. 系统.集合.通用;

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

当我将我的标准项目作为同一解决方案中的框架和核心项目的依赖项进行测试时,我没有注意到类似的情况,因此我怀疑这可能是 NuGet 的事情。

这里究竟发生了什么?如何在没有大量依赖项的情况下使我的 .NET Standard 库在 NuGet 上可用?

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


你没有做错任何事,这是预料之中的事情。如果您只想将自己的 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 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.Object被定义在一个System.Runtime.dll集会。所以System.Runtime.dll您最终在 .NET Framework 应用程序中得到的文件包含System.Runtime.dll包含转发到 .NET Framework 的类型mscorlib.dll。 .NET Core 已经包含了不同的System.Runtime.dll这对该平台做了一些不同的事情。此机制允许单个 DLL 文件在两个平台上工作,因为这些类型转发和附加实现确保在两个实现上工作的相同“契约”(类型 + 程序集 + 程序集版本)。

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

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

使用 .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 依赖项都会被删除,您将获得构建工具附带的支持库。

这个想法是 .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 中修复此问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我的 .NET Standard NuGet 包会触发如此多的依赖项? 的相关文章

  • 泛型和系统集合

    迁移到 NET 2 0 后 是否还有理由继续使用 systems Collections 命名空间 除了维护遗留代码之外 是否应该始终使用泛型命名空间 在大多数情况下 泛型集合的执行速度比非泛型集合更快 并且为您带来强类型集合的好处 比较
  • MSBuild 编译解决方案时找不到 SGen

    我在这里查看了其他几个与 SGen 相关的问题 要么他们的答案不适用 要么他们的答案不能为我解决这个问题 我安装了几个 SDK 来解决这个问题 但没有成功 不应更改引用类型 因为这是唯一出现问题的地方 一次建议是将 SGen exe 放入C
  • .NET 的 BLOB 分布式存储?

    我正在寻找一个经过相当好的测试的库 服务器来存储持久的分布式哈希表 我对使用基于 SQL 的解决方案犹豫不决 因为数据是高度面向文档的 由数百万个约 64KB 的 blob 组成 只有一个索引 由所述 BLOB 的哈希计算 并且需要能够进行
  • 在线找到具有两个不同参数的多个匹配绑定

    我在同一个功能文件中写了两行 何时 When user action1 key1 with value1 for atttributeType Value in Filename1 SectionId1 Then abc When user
  • 判断位图是否全黑的有效方法是什么?

    我想知道是否有一种超级有效的方法来确认 Image 对象引用全黑图像 因此位图中的每个像素都是 ARGB 255 0 0 0 你会推荐什么 大多数位图的尺寸为 1024 x 6000 像素 尽管假设它们始终是该尺寸并不安全 我需要这个 因为
  • 插入后,数据库中仅插入“字符串”的一个字符

    Below is my table screenshot Data after insertion C 代码 SqlConnection con new SqlConnection connectionsession Con con Ope
  • 为什么在此单元测试中,BackgroundWorker 没有在正确的线程上调用 RunWorkerCompleted?

    backgroundWorker 的全部目的是在执行耗时的任务后更新 UI 组件正如广告所宣传的那样在我的 WPF 应用程序中 但是在我的测试中 回调不会在调用线程上调用 Test public void TestCallbackIsInv
  • .NET 是否有相当于 Python 中的 **kwargs 的功能?

    我一直无法通过典型渠道找到这个问题的答案 在Python中我可以有以下函数定义 def do the needful kwargs Kwargs is now a dictionary i e do the needful spam 42
  • List 与 IEnumerable 的协变和逆变

    所以 假设我有 Public Interface ISomeInterface End Interface Public Class SomeClass Implements ISomeInterface End Class 如果我有MyL
  • 以线程安全的方式获取随机数

    这是一篇描述随机数线程安全性的好文章 以线程安全的方式获取随机数 http blogs msdn com b pfxteam archive 2009 02 19 9434171 aspx 但我坚持使用 RandomGen2 示例 publ
  • 使用编译时编织进行依赖注入? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我只是想了解 PostSharp 老实说我认为它太棒了 但有一件事对我来说很难如何纯依赖注入 不是服务定位器 无法完成 https cod
  • 无法在.net core中使用WCF WSHttpBinding

    我正在尝试将我的项目从 net 移动到 net core 我最初在 net 中使用 WCF WSHttpBinding 服务 但无法在 net core 中使用相同的服务 我尝试使用 BasicHttpBinding 在客户端与 WsHtt
  • C# 枚举 - 根据掩码检查标志

    我有以下枚举标志 Flags private enum MemoryProtection uint None 0x000 NoAccess 0x001 ReadOnly 0x002 ReadWrite 0x004 WriteCopy 0x0
  • 如果浏览器在 asp .net 中关闭,请从浏览器中注销?

    我的要求有点复杂 用户正在使用 Web 浏览器访问数据库 而在访问数据库时 如果用户关闭活动页面而不是注销会话 该会话需要自动注销 有人可以指导我如何做这个吗 我在母版页中使用了jquery onbeforeunload 我收到消息离开页面
  • 检查列表是否包含另一个列表。 C#

    编辑 只是说 ContainsAllItem 中的注释解释得最好 很抱歉问这个问题 我知道以前有人问过这个问题 但我只是不明白 好的 所以我想检查一个列表是否包含另一个列表中的所有项目WITHOUT重叠 以及根据类字符串 名称变量 称为项目
  • WebClient读取错误页面的内容

    我有一个加载页面内容的应用程序 我使用 WebClient 类 即使服务器返回 404 500 等错误 我也需要检索内容 我需要这样的东西 WebClient wc new WebClient string pageContent try
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 我应该如何在 VB.NET 中进行转换?

    所有这些都相等吗 在什么情况下我应该选择其中一个而不是其他 var ToString CStr 变量 CType 变量 字符串 DirectCast 变量 字符串 编辑 来自的建议不是我自己 https stackoverflow com
  • 在 .NET 中记录 StackOverflowException

    最近 我的 NET 应用程序 asp net 网站 中出现了堆栈溢出异常 我之所以知道该异常是因为它出现在我的 EventLog 中 我知道 StackOverflow 异常无法被捕获或处理 但是有没有办法在它杀死您的应用程序之前记录它 我
  • 将文本从文本文件添加到 PDF 文件[重复]

    这个问题在这里已经有答案了 这是我的代码 using FileStream msReport new FileStream pdfPath FileMode Create step 1 using Document pdfDoc new D

随机推荐