Zentrale Paketverwaltung (Central Package Management, CPM)
Die Abhängigkeitsverwaltung ist ein Kernfeature von NuGet. Das Verwalten von Abhängigkeiten für ein einzelnes Projekt kann einfach sein. Die Verwaltung von Abhängigkeiten für Multiprojektlösungen kann sich als schwierig erweisen, wenn sie mit der Skalierung in Größe und Komplexität beginnen. In Situationen, in denen Sie allgemeine Abhängigkeiten für viele verschiedene Projekte verwalten, können Sie die zentralen Paketverwaltungsfeatures (CPM) von NuGet nutzen, um all dies von einer einfachen Position aus zu erledigen.
Bisher wurden NuGet-Paketabhängigkeiten an einem von zwei Speicherorten verwaltet:
-
packages.config
– Eine XML-Datei, die in älteren Projekttypen verwendet wird, um die Liste der Pakete beizubehalten, auf die vom Projekt verwiesen wird. -
<PackageReference />
– Ein xml-Element, das in MSBuild-Projekten verwendet wird, definiert NuGet-Paketabhängigkeiten.
Ab NuGet 6.2-können Sie Ihre Abhängigkeiten in Ihren Projekten zentral verwalten, indem Sie eine Directory.Packages.props
Datei und eine MSBuild-Eigenschaft hinzufügen.
Das Feature ist in allen integrierten NuGet-Tools verfügbar, beginnend mit den folgenden Versionen.
Ältere Tools ignorieren zentrale Paketverwaltungskonfigurationen und -features. Um dieses Feature in vollem Umfang zu verwenden, stellen Sie sicher, dass alle Buildumgebungen die neuesten kompatiblen Toolversionen verwenden.
Die zentrale Paketverwaltung gilt für alle <PackageReference>
-basierten MSBuild-Projekte (einschließlich älteren CSPROJ-), solange kompatible Tools verwendet werden.
Aktivieren der zentralen Paketverwaltung
Um mit der zentralen Paketverwaltung zu beginnen, müssen Sie eine Directory.Packages.props
Datei im Stammverzeichnis Ihres Repositorys erstellen und die MSBuild-Eigenschaft ManagePackageVersionsCentrally
auf true
festlegen.
Sie können es manuell erstellen oder die dotnet CLI verwenden:
dotnet new packagesprops
Innerhalb definieren Sie dann jede der jeweiligen Paketversionen, die für Ihre Projekte erforderlich sind, mit <PackageVersion />
Elementen, die die Paket-ID und -Version definieren.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
Für jedes Projekt definieren Sie dann eine <PackageReference />
, lassen jedoch das Attribut Version
aus, da die Version von einem entsprechenden <PackageVersion />
-Eintrag abgerufen wird.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
</Project>
Jetzt verwenden Sie die zentrale Paketverwaltung und verwalten Ihre Versionen an einem zentralen Ort!
Zentrale Paketverwaltungsregeln
Die Directory.Packages.props
Datei verfügt über eine Reihe von Regeln im Hinblick darauf, wo sie sich im Verzeichnis eines Repositorys und im Kontext befindet. Aus Gründen der Einfachheit wird nur eine Directory.Packages.props
Datei für ein bestimmtes Projekt ausgewertet.
Was dies bedeutet: Wenn Sie mehrere Directory.Packages.props
Dateien in Ihrem Repository hatten, wird die Datei, die dem Verzeichnis Ihres Projekts am nächsten kommt, ausgewertet. Auf diese Weise können Sie auf verschiedenen Ebenen Ihres Repositorys zusätzliche Kontrolle haben.
Hier ist ein Beispiel, betrachten Sie die folgende Repositorystruktur:
Repository
|-- Directory.Packages.props
|-- Solution1
|-- Directory.Packages.props
|-- Project1
|-- Solution2
|-- Project2
- Project1 wertet die
Directory.Packages.props
Datei imRepository\Solution1\
Verzeichnis aus und muss die nächste bei Bedarf manuell importieren.<Project> <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" /> <ItemGroup> <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" /> </ItemGroup> </Project>
- Project2 wertet die
Directory.Packages.props
Datei im verzeichnisRepository\
aus.
Hinweis: MSBuild importiert nicht automatisch jede Directory.Packages.props
für Sie, nur die erste, die dem Projekt am nächsten kommt. Wenn Sie mehrere Directory.Packages.props
haben, müssen Sie das übergeordnete Element manuell importieren, während der Stamm Directory.Packages.props
nicht importiert würde.
Loslegen
Um Ihr Repository vollständig zu integrieren, sollten Sie die folgenden Schritte ausführen:
- Erstellen Sie eine neue Datei im Stammverzeichnis Ihres Repositorys mit dem Namen
Directory.Packages.props
, die die zentral definierten Paketversionen deklariert, und legen Sie die MSBuild-EigenschaftManagePackageVersionsCentrally
auftrue
fest. - Deklarieren Sie
<PackageVersion />
Elemente in IhrerDirectory.Packages.props
. - Deklarieren Sie
<PackageReference />
Elemente ohneVersion
Attribute in Ihren Projektdateien.
Eine Vorstellung davon, wie die zentrale Paketverwaltung aussehen kann, finden Sie in unserem Beispiel-Repository.
Transitives Fixieren
Sie können eine transitive Paketversion automatisch außer Kraft setzen, auch ohne eine explizite <PackageReference />
der obersten Ebene, indem Sie eine Funktion nutzen, die als transitives Fixieren bezeichnet wird. Dies fördert bei Bedarf eine transitive Abhängigkeit zu einer Abhängigkeit auf oberster Ebene.
Beachten Sie, dass Downgrades beim transitiven Anheften eines Pakets zulässig sind. Wenn Sie versuchen, ein Paket an eine niedrigere Version anzuheften als die von den Abhängigkeiten angeforderte Version, löst das Wiederherstellen einen NU1109 Fehler aus.
Sie können dieses Feature aktivieren, indem Sie die MSBuild-Eigenschaft CentralPackageTransitivePinningEnabled
auf true
in einem Projekt oder in einer Directory.Packages.props
- oder Directory.Build.props
-Importdatei festlegen:
<PropertyGroup>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
Transitives Anheften und Verpacken
Wenn ein Paket transitiv festgelegt ist, verwendet Ihr Projekt eine höhere Version als die von Ihren Abhängigkeiten angeforderte. Wenn Sie ein Paket aus Ihrem Projekt erstellen, sorgt NuGet dafür, dass Ihr Paket funktioniert, indem es die transitiv angehefteten Abhängigkeiten in explizite Abhängigkeiten im Nuspec-Format umwandelt.
Im folgenden Beispiel ist PackageA 1.0.0
von PackageB 1.0.0
abhängig.
<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>
Wenn Sie den Packbefehl zum Erstellen eines Pakets verwenden, werden beide Pakete in der Abhängigkeitsgruppe angezeigt.
<group targetFramework="net6.0">
<dependency id="PackageA" version="6.12.1" exclude="Build,Analyzers" />
<dependency id="PackageB" version="6.12.1" exclude="Build,Analyzers" />
</group>
Aus diesem Grund sollte die Verwendung transitiven Pinnings sorgfältig überlegt werden, wenn eine Bibliothek erstellt wird, da dies zu Abhängigkeiten führen kann, die Sie nicht erwartet haben.
Überschreiben von Paketversionen
Sie können eine einzelne Paketversion überschreiben, indem Sie die VersionOverride
-Eigenschaft für ein <PackageReference />
Element verwenden. Dadurch wird jedes zentral definierte <PackageVersion />
außer Kraft gesetzt.
<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>
Sie können dieses Feature deaktivieren, indem Sie die MSBuild-Eigenschaft CentralPackageVersionOverrideEnabled
auf false
in einem Projekt oder in einer Directory.Packages.props
- oder Directory.Build.props
-Importdatei festlegen:
<PropertyGroup>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>
Wenn dieses Feature deaktiviert ist, führt die Angabe eines VersionOverride
für ein beliebiges <PackageReference />
Element zu einem Fehler zur Wiederherstellungszeit, der angibt, dass das Feature deaktiviert ist.
Deaktivieren der zentralen Paketverwaltung
Wenn Sie die zentrale Paketverwaltung für ein bestimmtes Projekt deaktivieren möchten, können Sie es deaktivieren, indem Sie die MSBuild-Eigenschaft ManagePackageVersionsCentrally
auf false
festlegen:
<PropertyGroup>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
Globale Paketverweise
Anmerkung
Dieses Feature ist nur in Visual Studio 2022 17.4 oder höher, .NET SDK 7.0.100.preview7 oder höher und NuGet 6.4 oder höher verfügbar.
Ein globaler Paketverweis wird verwendet, um anzugeben, dass ein Paket von jedem Projekt in einem Repository verwendet wird. Dazu gehören Pakete, die Versionsverwaltung durchführen, den Build erweitern oder andere Pakete, die von allen Projekten benötigt werden. Globale Paketverweise werden der PackageReference-Elementgruppe mit den folgenden Metadaten hinzugefügt:
IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"
Dadurch wird sichergestellt, dass das Paket nur als Entwicklungsabhängigkeit verwendet wird und Kompilierungszeit-Assemblyreferenzen vermeidet.PrivateAssets="All"
Dadurch wird verhindert, dass globale Paketverweise von nachgeschalteten Abhängigkeiten aufgenommen werden.
GlobalPackageReference
-Elemente sollten in Ihrem Directory.Packages.props
platziert werden, um von jedem Projekt in einem Repository verwendet zu werden.
<Project>
<ItemGroup>
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.109" />
</ItemGroup>
</Project>
Warnung bei Verwendung mehrerer Paketquellen
Wenn Sie die zentrale Paketverwaltung verwenden, wird eine NU1507
Warnung angezeigt, wenn in Ihrer Konfiguration mehr als eine Paketquelle definiert ist. Um diese Warnung zu beheben, ordnen Sie Ihre Paketquellen mithilfe von Paketquellenzuordnung zu, oder geben Sie eine einzelne Paketquelle an.
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.
Anmerkung
Die zentrale Paketverwaltung befindet sich in der aktiven Entwicklung. Wir freuen uns, dass Sie es ausprobieren und Feedback geben, das Sie möglicherweise bei NuGet/Homehaben.