Централизованное управление пакетами (CPM)

Управление зависимостями является основной функцией NuGet. Для одного проекта управление зависимостями может быть простым. Для решений с несколькими проектами управление зависимостями может представлять трудности, так как их размер и сложность начинают расти. В ситуациях, когда вы управляете общими зависимостями в нескольких проектах, вы можете использовать функции централизованного управления пакетами NuGet, чтобы с легкостью выполнять все эти действия в одном расположении.

Исторически управление зависимостями пакетов NuGet выполнялось в одном из двух расположений:

  • packages.config: файл XML, используемый в проектах более старых типов для ведения списка пакетов, на которые ссылается проект.
  • <PackageReference /> — это XML-элемент, который используется в проектах MSBuild для определения зависимостей пакета NuGet.

Начиная с NuGet 6.2 вы можете централизованно управлять зависимостями в проектах с добавлением файла Directory.Packages.props и свойства MSBuild.

Эта функция доступна во всех интегрированных инструментах NuGet, начиная со следующих версий.

Более старые средства будут игнорировать конфигурации и функции централизованного управления пакетами. Чтобы использовать эту функцию в полной мере, убедитесь в том, что во всех средах разработки установлены последние версии совместимых инструментов.

Централизованное управление пакетами будет применяться ко всем проектам MSBuild на основе <PackageReference>, включая legacy .csproj, если используются совместимые инструменты.

Включение централизованного управления пакетами

Чтобы настроить централизованное управление пакетами, следует создать файл Directory.Packages.props в корне репозитория и задать для свойства MSBuild ManagePackageVersionsCentrally значение true.

В этом файле можно указать каждую из соответствующих версий пакетов, необходимых для ваших проектов, с помощью элементов <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 будет оценивать файл Directory.Packages.props в каталоге Repository\Solution1\, и при необходимости нужно вручную импортировать следующий файл.
    <Project>
      <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" />
      <ItemGroup>
        <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" />
      </ItemGroup>
    </Project>
    
  • Проект Project2 будет обрабатывать файл Directory.Packages.props в каталоге Repository\.

Примечание. MSBuild не будет автоматически импортировать для вас каждый Directory.Packages.props, а только первый, ближайший к проекту. Если у вас есть несколько Directory.Packages.props, необходимо вручную импортировать родительский элемент, поскольку корневой Directory.Packages.props этого не делает.

Начать

Чтобы полностью подключить репозиторий, выполните следующие действия:

  1. Создайте в корневом каталоге репозитория новый файл с именем Directory.Packages.props, где объявляются централизованно определенные версии пакетов, и задайте для свойства MSBuild ManagePackageVersionsCentrally значение true.
  2. Объявите элементы <PackageVersion /> в файле Directory.Packages.props.
  3. Объявите элементы <PackageReference /> без атрибутов Version в файлах проекта.

Чтобы понять, что собой представляет централизованное управление пакетами, изучите репозиторий примеров.

Транзитивное закрепление

Вы можете автоматически переопределить транзитивную версию пакета даже без явного верхнего уровня <PackageReference /> с помощью функции, называемой транзитивным закреплением. Это неявным образом повышает транзитивную зависимость до зависимости верхнего уровня от вашего имени при необходимости.

Чтобы включить эту функцию, задайте для свойства MSBuild CentralPackageTransitivePinningEnabled значение true в проекте или в файле импорта Directory.Packages.props или Directory.Build.props:

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

Переопределение версий пакетов

Вы можете переопределить отдельную версию пакета, используя свойство VersionOverride элемента <PackageReference />. Оно переопределяет все централизованно заданные свойства <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>

Чтобы отключить эту функцию, задайте для свойства MSBuild CentralPackageVersionOverrideEnabled значение false в проекте или в файле импорта Directory.Packages.props или Directory.Build.props:

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

Если эта функция отключена, указание VersionOverride для элемента <PackageReference /> приведет к ошибке во время восстановления. Это указывает на то, что функция отключена.

Отключение централизованного управления пакетами

Если вы хотите отключить централизованное управление пакетами для любого конкретного проекта, задайте для свойства MSBuild ManagePackageVersionsCentrally значение false:

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

Глобальные ссылки на пакеты

Примечание.

Эта функция доступна только в Visual Studio 2022 17.4 или более поздней версии, пакет SDK для .NET 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.