中央包管理 (CPM)

依赖项管理是 NuGet 的核心功能。 管理单个项目的依赖项很简单。 而对于多项目解决方案的依赖项,随着规模开始变化,复杂程度增加,管理起来就很困难。 如果你在管理许多不同项目的常见依赖项,可利用 NuGet 的中央包管理 (CPM) 功能从一个位置轻松完成所有管理任务。

以前,NuGet 包依赖项主要在两个位置之一进行管理:

  • packages.config - 旧项目类型中使用 XML 文件维护项目引用的包的列表。
  • <PackageReference /> - MSBuild 项目中使用的 XML 元素定义 NuGet 包依赖项。

NuGet 6.2 开始,可以通过添加 Directory.Packages.props 文件和 MSBuild 属性集中管理项目中的依赖项。

此功能适用于所有 NuGet 集成工具,从以下版本开始。

旧版工具将忽略中央包管理配置和功能。 若要充分使用此功能,请确保你所有的生成环境都使用最新的兼容工具版本。

只要使用兼容的工具,中央包管理就应用于所有基于 <PackageReference> 的 MSBuild 项目(包括旧 CSPROJ)。

启用中央包管理

若要开始使用中央包管理,必须在存储库的根目录中创建一个 Directory.Packages.props 文件,并将 MSBuild 属性 ManagePackageVersionsCentrally 设置为 true

然后,在其中使用定义包 ID 和版本的 <PackageVersion /> 元素定义项目所需的每个相应的包版本。

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
  </ItemGroup>
</Project>

然后,为每个项目定义一个 <PackageReference /> 但省略 Version 属性,因为版本将从相应的 <PackageVersion /> 项获得。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" />
  </ItemGroup>
</Project>

现在,你即可使用中央包管理并在一个集中的位置管理版本了!

中央包管理规则

关于 Directory.Packages.props 文件在存储库目录及其上下文中的位置,存在许多规则。 为简单起见,只评估给定项目的一个 Directory.Packages.props 文件。

这意味着,如果存储库中有多个 Directory.Packages.props 文件,将会评估最靠近项目目录的文件。 这样,就可以在存储库的各个级别额外进行控制。

下面是一个示例,请看以下存储库结构:

Repository
 |-- Directory.Packages.props
 |-- Solution1
     |-- Directory.Packages.props
     |-- Project1
 |-- Solution2
     |-- Project2
  • Project1 将评估 Repository\Solution1\ 目录中的 Directory.Packages.props 文件,并且必须根据需要手动导入下一个文件。
    <Project>
      <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" />
      <ItemGroup>
        <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" />
      </ItemGroup>
    </Project>
    
  • Project2 将评估 Repository\ 目录中的 Directory.Packages.props 文件。

注意:MSBuild 不会自动为你导入每个 Directory.Packages.props,只会为你导入最接近项目的第一个。 如果有多个 Directory.Packages.props,则必须手动导入父级,而根 Directory.Packages.props 不需要。

开始使用

若要完全载入存储库,请考虑执行以下步骤:

  1. 在存储库的根目录创建一个名为 Directory.Packages.props 的新文件,用于声明在其中集中定义的包版本并将 MSBuild 属性 ManagePackageVersionsCentrally 设置为 true
  2. Directory.Packages.props 中声明 <PackageVersion /> 项。
  3. 在项目文件中声明不带 Version 属性的 <PackageReference /> 项。

若要了解中央包管理可能是什么样子,请参阅示例存储库

可传递固定

即使没有显式的顶级 <PackageReference />,你也可以选择称为可传递固定的功能来自动替代可传递包版本。 这样可在必要时代表你将可传递依赖项隐式地提升为顶级依赖项。

可通过在项目中或在 Directory.Packages.propsDirectory.Build.props 导入文件中将 MSBuild 属性 CentralPackageTransitivePinningEnabled 设置为 true 来启用此功能:

<PropertyGroup>
  <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>

替代包版本

可对 <PackageReference /> 项使用 VersionOverride 属性来替代单个包版本。 这样可以替代任何集中定义的 <PackageVersion />

<Project>
  <ItemGroup>
    <PackageVersion Include="PackageA" Version="1.0.0" />
    <PackageVersion Include="PackageB" Version="2.0.0" />
  </ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="PackageA" VersionOverride="3.0.0" />
  </ItemGroup>
</Project>

可通过在项目中或在 Directory.Packages.propsDirectory.Build.props 导入文件中将 MSBuild 属性 CentralPackageVersionOverrideEnabled 设置为 false 来禁用此功能:

<PropertyGroup>
  <CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>

禁用此功能后,在任何 <PackageReference /> 项上指定 VersionOverride 将导致还原时出现表明该功能已禁用的错误。

禁用中央包管理

如果要禁用任何特定项目的中央包管理,可以通过将 MSBuild 属性 ManagePackageVersionsCentrally 设置为 false

<PropertyGroup>
  <ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>

全局包引用

注意

此功能仅适用于 Visual Studio 2022 17.4 或更高版本、.NET SDK 7.0.100.preview7 或更高版本以及 NuGet 6.4 或更高版本。

全局包引用用于指定由存储库中的每个项目使用使用某个包。 这包括进行版本控制、扩展构建的软件包,或所有项目都需要的其他包。 全局包引用将添加到具有以下元数据的 PackageReference 项组:

  • IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"
    这可确保软件包仅用作开发依赖项,并防止编译时引用任何程序集。
  • PrivateAssets="All"
    这可以防止下游依赖项选取全局包引用。

GlobalPackageReference 项目应放在您的 Directory.Packages.props 中,供版本库中的每个项目使用:

<Project>
  <ItemGroup>
    <GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.109" />
  </ItemGroup>
</Project>

使用多个包源时发出警告

使用中央包管理时,如果配置中定义了多个包源,你将看到 NU1507 警告。 若要消除此警告,请使用包源映射为包源创建映射或指定单个包源。

There are 3 package sources defined in your configuration. When using central package management, please map your package sources with package source mapping (https://aka.ms/nuget-package-source-mapping) or specify a single package source.

注意

中央包管理正在积极开发中。 欢迎在 NuGet/Home 上体验并提供任何反馈。