NuGet 依赖策略

ibe*_*dev 5 c# nuget nuget-package nuspec

我将许多应用程序模型和接口拆分为自己的 nuGet 包。

问题是:在创建有关依赖项定义的 nuGet 包时,是否有任何好的实践推荐策略?

有时 apackage A取决于 a package B。如果我没有package B在我的 nuspec 上声明特定版本package A,当我稍后在任何解决方案中导入package AnuGet 包时,它可能会在运行时失败,因为子依赖项不可用。

有时依赖树甚至会更深。但如果我明确地将依赖项添加到每个 nuspec 文件中,那么我稍后可能会发现版本冲突。

问题是:如果一切都在我的控制之下,处理这些事情的推荐策略是什么?我是否应该只在项目的依赖项“不明显”时指定依赖项(例如:导入 nuGet 包装器的项目在运行时需要但不直接使用的第三方库)?我应该总是这样做,然后以不同的方式处理版本冲突吗?任何有关这方面的良好信息来源将不胜感激,因为我找到了几个例子,但没有推荐某种特定的做事方式。

附件:我创建 nuGet 包的方式是包含我手动编辑的 nuspec 文件。例如,如果我有以下解决方案结构:

ToolBelt.CityContracts.sln
-ToolBelt.CityContracts.NuGet
--ToolBelt.CityContracts.NuGet.nuspec
-ToolBelt.CityContractsOne
-ToolBelt.CityContractsTwo
Run Code Online (Sandbox Code Playgroud)

ToolBelt.CityContractsOne我有ToolBelt.CityContractsTwo我的 C# 源文件。在ToolBelt.CityContracts.NuGet项目中,我添加了一个引用ToolBelt.CityContractsOneToolBelt.CityContractsTwo确保 nuspec“知道”源文件在哪里。

然后 nuspec 看起来像这样:

ToolBelt.CityContracts.sln
-ToolBelt.CityContracts.NuGet
--ToolBelt.CityContracts.NuGet.nuspec
-ToolBelt.CityContractsOne
-ToolBelt.CityContractsTwo
Run Code Online (Sandbox Code Playgroud)

直到这里一切都很标准。

nupkgs然后我使用 nuget 命令工具在使用以下命令调用的文件夹内生成 nuget 包:

nuget pack ToolBelt.CityContracts.NuGet.nuspec -Version $VERSION -OutputDirectory nupkgs -Prop Configuration=Release -NoDefaultExcludes -Verbosity detailed
Run Code Online (Sandbox Code Playgroud)

更新 1: 目前我的策略如下。

  1. 如果package A在其公共 API 中公开属于 a 一部分的类/接口package B,则package A不会在其 nuspec 中添加依赖项package B。因此添加的项目package A也必须显式添加package B
  2. 如果package A未在其公共 API 中公开属于 a 一部分的类/接口package B,但在内部使用它们,则package A必须在其 nuspec 中添加依赖项package B,以便添加的项目package A也将package B自动安装并避免运行时异常风险。

这个想法是:如果代码可以编译,它应该运行而不会由于不存在的依赖项而出现运行时异常。

这对我来说是有道理的,但我找不到任何可靠的来源来证实这是正确的方法。

ziv*_*kan 2

由于您的目标是 netstandard2.0,创建包的更简单方法是使用dotnet pack,而不是自己创建 nuspec 并使用nuget pack. dotnet pack或者msbuild /t:pack将从 csproj 中提取元数据,并自动将任何 PackageReference 添加为包的依赖项。如果您不希望包的用户获得构建时依赖项,则可以使用PrivateAssets

最佳实践是将所有运行时依赖项作为依赖项添加到包中,这样任何仅引用您的包的人的程序都不会因缺少 dll 而在运行时崩溃。当不同的包请求不同的版本时,NuGet 恢复会自动处理依赖项版本的选择,因此您通常不应该花太多时间担心,尽管坚持语义版本控制会有所帮助。

顺便说一句,我个人的观点是包越少越好。接口的实现可能与接口的定义位于不同的程序集/包中,这绝对是有充分理由的。但除非你能用充分的理由证明它是合理的,否则我建议将接口和实现保留在同一个程序集/包中。我过去工作的一个代码库的代码位于多个存储库的多个包中,因为团队认为某些通用代码可能对其他项目有用。但是错误修复意味着您必须创建新版本的依赖项,然后更新已部署应用程序中的引用,并且依赖项的调试很困难。当我们必须处理该依赖包时,这会显着减慢开发速度,并且最终没有其他东西使用它,因此拆分它实际上没有任何好处。