NuGet依赖策略

时间:2018-10-22 08:47:54

标签: c# nuget nuget-package nuspec

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

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

有时package A取决于package B。如果我未在package B的nuspec上声明特定的package A版本,则稍后在任何解决方案中导入package A nuGet程序包时,它可能会在运行时失败,因为其从属关系无法使用。

有时,依赖关系树会更深入。但是,如果我将依赖项显式添加到每个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必须向{{ 1}},这样添加package B的项目也将自动安装package A并避免运行时异常风险。

这个想法是:如果代码可以编译,则由于不存在依赖关系,它应该在没有运行时异常的情况下运行。

这对我来说很有意义,但是我找不到任何可靠的消息来源来确认这是可行的方法。

1 个答案:

答案 0 :(得分:1)

由于您的目标是netstandard2.0,因此创建软件包的一种简便方法是使用dotnet pack,而不是自己创建并使用nuget pack来创建nuspec。 dotnet packmsbuild /t:pack将从csproj中提取元数据,并自动将任何PackageReference作为依赖项添加到您的软件包中。如果您不希望获得包用户,则可以使用PrivateAssets

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

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