繁体   English   中英

Visual Studio/nuget 如何决定要下载/精确的软件包版本?

[英]How does visual studio/nuget decides what version(s) of the package to download/exact?

这是一个 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# 项目,编译器抱怨缺少对 log4net 的引用

“直截了当” 回答:您不必担心。 在项目中安装或升级包时,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,然后重新安装。 您还可以考虑从 packages.config 迁移到 PackageReference ,它没有 packages.config 具有的提示路径问题。

长而详细的答案:使用 NuGet 时,“版本”一词通常指的是包版本,在本例中为 1.2.11。 查看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 具有兼容 TFM 的复杂映射,它用于为您的项目选择 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 上的包相比,该包在 nupkg 中的不同位置具有 dll。组织。 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 写入一个文件obj\\project.assets.json包含编译器使用的所选资产的路径,这意味着如果您更改源代码存储库结构,只需执行 NuGet 还原即可修复它,而使用 packages.config 您可能需要重新安装每个在每个项目中打包)。 使用随 .NET Core 引入的新 SDK 样式的项目根本不支持 packages.config,无论值多少钱。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM