NuGet 依赖项策略



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

问题是:在创建有关依赖项定义的 nuGet 包时,是否有任何建议的良好做法策略?

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

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

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

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

ToolBelt.CityContracts.sln
-ToolBelt.CityContracts.NuGet
--ToolBelt.CityContracts.NuGet.nuspec
-ToolBelt.CityContractsOne
-ToolBelt.CityContractsTwo

ToolBelt.CityContractsOneToolBelt.CityContractsTwo中,我有我的 c# 源文件。从ToolBelt.CityContracts.NuGet项目中,我添加了对ToolBelt.CityContractsOneToolBelt.CityContractsTwo的引用,以确保 nuspec"知道"源文件的位置。

然后 nuspec 看起来像这样:

<?xml version="1.0" encoding="utf-8" ?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>ToolBelt.CityContracts</id>
<version>1.0.0</version>
<authors>iberodev</authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Shared Contracts</description>
<dependencies>
<!--here sub-dependencies that I want to drag across-->
</dependencies>
</metadata>
<files>
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsOne.dll" target="lib/netstandard2.0" />
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsOne.pdb" target="lib/netstandard2.0" />
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsTwo.dll" target="lib/netstandard2.0" />
<file src="bin/*/netstandard2.0/ToolBelt.CityContractsTwo.pdb" target="lib/netstandard2.0" />
</files>
</package>

一切都很标准,直到这里。

然后,我使用 nuget 命令工具在名为nupkgs的文件夹中生成 nuget 包,其中包含以下命令:

nuget pack ToolBelt.CityContracts.NuGet.nuspec -Version $VERSION -OutputDirectory nupkgs -Prop Configuration=Release -NoDefaultExcludes -Verbosity detailed

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

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

这个想法是:如果代码编译,它应该在没有运行时异常的情况下运行,

因为不存在依赖项。这对我来说是有道理的,但我找不到任何可靠的消息来源来确认这是要走的路。

由于您的目标是 netstandard2.0,因此创建包的更简单方法是使用 dotnet pack,而不是自己创建 nuspec 并使用nuget packdotnet packmsbuild /t:pack将从 csproj 中提取元数据,并自动将任何包引用作为依赖项添加到包中。如果你有一个不希望包的用户获取的生成时依赖项,则可以使用 PrivateAssets。

最佳做法是将所有运行时依赖项作为依赖项添加到包中,以便仅引用包的任何人,其程序不会因缺少 dll 而在运行时崩溃。当不同的包请求不同的版本时,NuGet 还原会自动处理依赖项版本的选择,因此通常不应花费太多时间担心这一点,尽管坚持使用语义版本控制会有所帮助。

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

最新更新