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 kataloguRepository\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 kataloguRepository\
.
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:
- 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ść MSBuildManagePackageVersionsCentrally
natrue
. - Zadeklaruj elementy
<PackageVersion />
wDirectory.Packages.props
. - Zadeklaruj elementy
<PackageReference />
bez atrybutówVersion
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.