【问题标题】:How does visual studio/nuget decides what version(s) of the package to download/exact?Visual Studio/nuget 如何决定要下载/精确的软件包版本?
【发布时间】:2019-03-16 03:21:02
【问题描述】:

这是一个 C# 项目。我了解 nuget 会咨询 packages.config 以获取下载/提取包的信息。但是我注意到它为不同的.net 平台下载了多个版本。例如,在 packages.config 中:

<package id="log4net" version="1.2.11" targetFramework="net461"/>

nuget 下载从 net10 到 net40 的所有版本。另外,.csproj文件中指定的位置与物理位置不一致。

在上面的示例中,.csproj 中的位置类似于:

src/packages/lognet.1.2.11/lib/log4net.dll

然而,该 dll 的物理位置是:

src/packages/log4net1.2.11/lib/netXX-full/log4net.dll

XX可以是10到40,前面说过,log4net下载解压了多个版本。

由于不一致,项目注定失败,引用包未找到错误。

我应该如何解决这个问题?

仅供参考:几天前我问了一个相关但不同的问题。

C# project, compiler complaining missing reference to log4net

【问题讨论】:

  • 您的项目的目标是什么框架?我认为你把事情搞混了,因此不一致。尝试做一个干净的构建。提供更多信息:完整的 packages.config 和没有文件的 project.csproj 文件的内容(只是 refs 和框架)

标签: .net visual-studio nuget log4net


【解决方案1】:

“直截了当”回答:您不必担心。当您在项目中安装或升级包时,NuGet 会告诉项目系统在 csproj 中放入什么。请注意,这与还原软件包不同。在 packages.config 项目中安装包意味着 Visual Studio 将同时修改 packages.config 文件和 csproj 文件。当您的计算机上没有 nuget 包时,当 NuGet 下载并解压缩它时,这称为还原,而不是安装。在上一个问题中,您说您克隆了其他人的存储库并且您正在尝试构建它。您可以询问他们 csproj 如何/为什么与 nuget.org 上的 log4net 包不匹配。或者在 Visual Studio 中,按 ctrl-q 进行搜索,键入“包管理器控制台”并选择它。初始化后,在“默认项目”下拉列表中选择带有错误 log4net 引用的项目,然后输入Update-Package -reinstall。这应该解决它。或者,您可以在解决方案资源管理器中右键单击项目,选择管理 NuGet 包,卸载 log4net 然后再次安装。也可以考虑migrating from packages.config to PackageReference,它没有packages.config的这个提示路径问题。

长而详细的回答:在使用 NuGet 时,“版本”一词通常指的是包版本,在本例中为 1.2.11。查看package page on nuget.org,在版本历史记录下,我们可以看到其他版本,例如 1.2.10、2.0.0、2.0.1 直至 2.0.8。除非您有多个项目,每个项目都引用不同版本的包,否则 NuGet 不会下载多个版本。

.NET 有不同版本的运行时,其中一些与其他版本不兼容,但这些被称为目标框架名字对象 (TFM),尽管不为 Microsoft 工作的人倾向于将它们称为目标框架或类似的东西。它类似于 Java、Python、PHP 等其他托管运行时或脚本语言,但可能更复杂,因为过去创建了大量 TFM,主要用于具有不同功能的不同移动设备。此外,Windows 运行时分为 3 个“家族”,其中 TFM 向后兼容,但仅在同一个“家族”内。 Nuget Client has a complex mapping of compatible TFMs 用于为您的项目选择 NuGet 包中最接近的兼容 TFM。

一个包可能包含用于不同 TFM 的多个 dll 的另一个原因是,他们希望在较新的 TFM 中使用较新的 API,同时仍允许针对较旧 TFM 的项目在没有新 API 的情况下使用该包。例如,虽然 net45、net46、net47 和很快的 net48 都与 net40 兼容,但 net40 没有 async-await。因此,一个包可能有一个 net40 dll,因此以 net40 为目标的项目仍然可以使用该包,但该包也可以包含一个带有额外异步 API 的 net45 dll。 net1x、net 2x 和 net3x 太老了(net40 和 net45 也是如此),以至于软件包很少再为这些旧版本提供 dll。然而,log4net 1.2.11 于 2011 年发布,当时这些较旧的 TFM 可能仍然很常见,值得为其提供兼容性。

所以,您在 log4net 包的 lib 文件夹中看到的并不是不同版本的 log4net,它实际上是相同版本的 log4net,但针对不同的 TFM 编译。这增加了可以使用该包的项目数量。

您正在使用的项目的 HintPath 不存在的原因有多种。鉴于您迄今为止提供的信息信息,听起来像是有人手动编辑了 csproj,或者有人创建了自己的 log4net v1.2.11 nuget 包,与 nuget 上的包相比,该包的 dll 在 nupkg 中的不同位置。组织。 NuGet 包被设计为不可变的,这意味着下载具有特定包 ID(名称)和包版本的 nupkg 应与来自任何其他 NuGet 源的具有相同包 ID + 版本的所有其他 nupkg 相同。如果不是这样,当 NuGet 从与安装包的人不同的来源恢复包时,您可能会遇到构建错误。

最后,带有 packages.config 的 NuGet 并非旨在手动编辑。您不应自己编辑和保存csproj 中的packages.config 文件或References 或HintPath。使用 NuGet 包管理器 UI 或包管理器控制台来安装、卸载和升级包。 NuGet 客户端中有很多逻辑,而不仅仅是资产选择,如果包使用特定功能,您会出错。

在 Visual Studio 2017 中,NuGet 添加了一种引用包的新方法,称为 PackageReference。您可能需要转到工具->选项,找到 NuGet 包管理器->常规,然后更改默认包管理格式或启用“允许在首次安装包时选择格式”。还应该可以右键单击许多项目类型并选择迁移到 PackageReference,但尚未对所有项目类型(主要是 ASP.NET)启用此功能。 PackageReference 不支持 packages.config 支持的某些功能,并且某些项目类型也不支持 PackageReference。但在最常见的情况下它是受支持的,如果你可以使用它,它有几个优点,包括不再在你的 csproj 中放置提示路径并避免你当前遇到的特定问题(在恢复时 NuGet 写入文件@ 987654326@ 包含编译器使用的选定资产的路径,这意味着如果您更改源代码存储库结构,只需执行 NuGet 还原即可修复它,而使用 packages.config 您可能需要重新安装每个项目中的每个包)。使用随 .NET Core 引入的新 SDK 样式的项目根本不支持 packages.config,无论其价值如何。

哇,我漫步的时间比我预期的要长得多。我希望它对您有所帮助而不是让您感到困惑。

【讨论】:

  • 非常感谢您的热心帮助!这是最新的更新:我已经建立了这个项目!我发现除了项目引用的 src/packages 文件夹之外,还有一个 .nuget/packages 文件夹。我最好的猜测是 .nuget/packages 是本地存储库,是从 src/packages 复制而来的,packages.config 没有得到尊重,并且 .nuget/packages 包含陈旧的 DLL。删除后,DLL 重新恢复并正确引用。
猜你喜欢
  • 1970-01-01
  • 2019-05-15
  • 1970-01-01
  • 2020-08-03
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 2019-02-14
  • 1970-01-01
相关资源
最近更新 更多