Udostępnij za pośrednictwem


Centralne zarządzanie pakietami (CPM)

Zarządzanie zależnościami to podstawowa funkcja narzędzia NuGet. Zarządzanie zależnościami dla pojedynczego projektu może być łatwe. Zarządzanie zależnościami dla rozwiązań wieloprojektowych może okazać się trudne, ponieważ zaczynają skalować rozmiar i złożoność. W sytuacjach, w których zarządzasz wspólnymi zależnościami dla wielu różnych projektów, możesz korzystać z funkcji zarządzania pakietami centralnymi (CPM) NuGet, aby to zrobić z jednego miejsca.

W przeszłości zależności pakietów NuGet były zarządzane w jednej z dwóch lokalizacji:

  • packages.config — plik XML używany w starszych typach projektów do obsługi listy pakietów, do których odwołuje się projekt.
  • <PackageReference /> — element XML używany w projektach MSBuild definiuje zależności pakietów NuGet.

Począwszy od NuGet 6.2, można centralnie zarządzać zależnościami w projektach przy użyciu dodawania pliku Directory.Packages.props i właściwości MSBuild.

Funkcja jest dostępna we wszystkich zintegrowanych narzędziach NuGet, począwszy od następujących wersji.

Starsze narzędzia ignorują centralne konfiguracje i funkcje zarządzania pakietami. Aby korzystać z tej funkcji w najszerszym zakresie, upewnij się, że wszystkie środowiska kompilacji korzystają z najnowszych zgodnych wersji narzędzi.

Centralne zarządzanie pakietami ma zastosowanie do wszystkich projektów MSBuild opartych na <PackageReference>(w tym starszychCSPROJ ), o ile są używane zgodne narzędzia.

Włączenie centralnego zarządzania pakietami

Aby rozpocząć zarządzanie pakietami centralnymi, należy utworzyć plik Directory.Packages.props w katalogu głównym repozytorium i ustawić właściwość MSBuild ManagePackageVersionsCentrally na true.

Możesz utworzyć go ręcznie lub użyć interfejsu wiersza polecenia dotnet:

dotnet new packagesprops

Wewnątrz, należy następnie zdefiniować każdą z odpowiednich wersji pakietów wymaganych przez projekty, korzystając z elementów <PackageVersion />, które określają identyfikator i wersję pakietu.

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

Dla każdego projektu należy zdefiniować <PackageReference />, ale pominąć atrybut Version, ponieważ wersja zostanie uzyskana z odpowiadającego elementu <PackageVersion />.

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

Teraz używasz centralnego zarządzania pakietami i zarządzania wersjami w centralnej lokalizacji!

Centralne reguły zarządzania pakietami

Plik Directory.Packages.props zawiera szereg reguł dotyczących lokalizacji w katalogu repozytorium i jego kontekście. Dla uproszczenia tylko jeden plik Directory.Packages.props jest oceniany dla danego projektu.

Oznacza to, że jeśli w repozytorium znajduje się wiele plików Directory.Packages.props, zostanie oceniony plik, który znajduje się najbliżej katalogu projektu. Umożliwia to dodatkową kontrolę na różnych poziomach repozytorium.

Oto przykład: proszę rozważyć następującą strukturę repozytorium:

Repository
 |-- Directory.Packages.props
 |-- Solution1
     |-- Directory.Packages.props
     |-- Project1
 |-- Solution2
     |-- Project2
  • Program Project1 oceni plik Directory.Packages.props w katalogu Repository\Solution1\ i w razie potrzeby ręcznie zaimportuje następny plik.
    <Project>
      <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" />
      <ItemGroup>
        <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" />
      </ItemGroup>
    </Project>
    
  • Program Project2 oceni plik Directory.Packages.props w katalogu Repository\.

Uwaga: program MSBuild nie zaimportuje automatycznie każdego Directory.Packages.props, tylko pierwszego znajdującego się najbliżej projektu. Jeśli masz wiele Directory.Packages.props, musisz zaimportować element nadrzędny ręcznie, podczas gdy Directory.Packages.props katalogu głównego nie zostanie zaimportowany.

Zacznij

Aby w pełni zintegrować repozytorium, rozważ wykonanie następujących kroków:

  1. Utwórz nowy plik w katalogu głównym repozytorium o nazwie Directory.Packages.props, który deklaruje centralnie zdefiniowane wersje pakietów i ustaw właściwość MSBuild ManagePackageVersionsCentrally na true.
  2. Zadeklaruj elementy <PackageVersion /> w Directory.Packages.props.
  3. Zadeklaruj elementy <PackageReference /> bez atrybutów Version w plikach projektu.

Aby dowiedzieć się, jak może wyglądać centralne zarządzanie pakietami, zapoznaj się z naszym repozytorium przykładów .

Przypinanie przechodnie

Możesz automatycznie zastąpić przechodnią wersję pakietu nawet bez jawnego <PackageReference /> najwyższego poziomu, decydując się na funkcję znaną jako przejściowe przypinanie. W razie potrzeby zwiększa to zależność przechodnią do zależności najwyższego poziomu niejawnie w Twoim imieniu. Należy pamiętać, że obniżanie wersji jest dozwolone w przypadku przejściowego przypinania pakietu. Jeśli spróbujesz przypiąć pakiet do niższej wersji niż ta żądana przez zależności, przywracanie zgłosi błąd NU1109.

Tę funkcję można włączyć, ustawiając właściwość MSBuild CentralPackageTransitivePinningEnabled na true w projekcie lub w pliku importu Directory.Packages.props lub Directory.Build.props:

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

Przejściowe przypinanie i pakowanie

Gdy pakiet jest przechodnio przypięty, projekt używa wyższej wersji pakietu niż ta żądana przez zależności. Jeśli tworzysz pakiet z projektu, aby upewnić się, że pakiet będzie działać poprawnie, NuGet będzie promował przechodnio przypięte zależności do jawnych zależności w nuspec.

W poniższym przykładzie PackageA 1.0.0 ma zależność od PackageB 1.0.0.

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

Gdy używasz polecenia pack do utworzenia pakietu, oba pakiety będą wyświetlane w grupie zależności.

      <group targetFramework="net6.0">
        <dependency id="PackageA" version="1.0.0" exclude="Build,Analyzers" />
        <dependency id="PackageB" version="2.0.0" exclude="Build,Analyzers" />
      </group>

W związku z tym użycie przypinania pośredniego powinno być dokładnie oceniane podczas tworzenia biblioteki, ponieważ może to prowadzić do nieoczekiwanych zależności.

Zastępowanie wersji pakietów

Pojedynczą wersję pakietu można zastąpić przy użyciu właściwości VersionOverride w elemencie <PackageReference />. Spowoduje to zastąpienie wszelkich <PackageVersion /> zdefiniowanych centralnie.

<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>

Tę funkcję można wyłączyć, ustawiając właściwość MSBuild CentralPackageVersionOverrideEnabled na false w projekcie lub w pliku importu Directory.Packages.props lub Directory.Build.props:

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

Gdy ta funkcja jest wyłączona, określenie VersionOverride dla dowolnego elementu <PackageReference /> spowoduje błąd podczas przywracania wskazujący, że funkcja jest wyłączona.

Wyłączanie centralnego zarządzania pakietami

Jeśli chcesz wyłączyć centralne zarządzanie pakietami dla dowolnego określonego projektu, możesz go wyłączyć, ustawiając właściwość MSBuild ManagePackageVersionsCentrally na false:

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

Odwołania do pakietów globalnych

Notatka

Ta funkcja jest dostępna tylko w programie Visual Studio 2022 17.4 lub nowszym, zestawie .NET SDK 7.0.100.preview7 lub nowszym oraz NuGet 6.4 lub nowszym.

Globalne odwołanie do pakietu służy do określania, że pakiet będzie używany przez każdy projekt w repozytorium. Obejmuje to pakiety, które wykonują przechowywanie wersji, rozszerzanie kompilacji lub inne pakiety wymagane przez wszystkie projekty. Odwołania do pakietów globalnych są dodawane do grupy elementów PackageReference z następującymi metadanymi:

  • IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"
    Gwarantuje to, że pakiet jest używany tylko jako zależność programistyczne i zapobiega wszelkim odwołaniom zestawów w czasie kompilacji.
  • PrivateAssets="All"
    Uniemożliwia to pobieranie odwołań do pakietów globalnych przez zależności podrzędne.

Elementy GlobalPackageReference powinny zostać umieszczone w Directory.Packages.props, aby mogły być używane przez każdy projekt w repozytorium.

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

Ostrzeżenie dotyczące korzystania z wielu źródeł pakietów

W przypadku korzystania z centralnego zarządzania pakietami zostanie wyświetlone ostrzeżenie NU1507, jeśli w konfiguracji zdefiniowano więcej niż jedno źródło pakietu. Aby rozwiązać to ostrzeżenie, zamapuj źródła pakietów przy użyciu mapowania źródła pakietów lub określ jedno źródło pakietu.

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.

Notatka

Centralne zarządzanie pakietami jest w aktywnym rozwoju. Dziękujemy za wypróbowanie tego rozwiązania i przekazanie wszelkich opinii, które możesz uzyskać w NuGet/Home.