Gestione pacchetti centrale (CPM)
La gestione delle dipendenze è una funzionalità di base di NuGet. La gestione delle dipendenze per un singolo progetto può essere semplice. La gestione delle dipendenze per le soluzioni multiprogetto può rivelarsi difficile quando iniziano a crescere in termini di dimensioni e complessità. In situazioni in cui si gestiscono le dipendenze comuni per molti progetti diversi, è possibile sfruttare le funzionalità di gestione centrale dei pacchetti (CPM) di NuGet per eseguire tutto questo, dalla facilità di una singola posizione.
Storicamente, le dipendenze dei pacchetti NuGet sono state gestite in una delle due posizioni seguenti:
-
packages.config
: file XML usato nei tipi di progetto meno recenti per mantenere l'elenco dei pacchetti a cui fa riferimento il progetto. -
<PackageReference />
: un elemento XML usato nei progetti MSBuild definisce le dipendenze del pacchetto NuGet.
A partire da NuGet 6.2, è possibile gestire centralmente le dipendenze nei progetti con l'aggiunta di un file Directory.Packages.props
e una proprietà MSBuild.
La funzionalità è disponibile in tutti gli strumenti integrati NuGet, a partire dalle versioni seguenti.
Gli strumenti meno recenti ignoreranno le configurazioni e le funzionalità di gestione dei pacchetti centrali. Per usare questa funzionalità nel modo più completo, assicurarsi che tutti gli ambienti di compilazione usino le versioni più recenti degli strumenti compatibili.
La gestione centrale dei pacchetti si applica a tutti i progetti MSBuild basati su <PackageReference>
(incluso CSPROJ legacy) purché vengano usati strumenti compatibili.
Abilitazione della gestione pacchetti centrale
Per iniziare a usare la gestione centrale dei pacchetti, è necessario creare un file Directory.Packages.props
nella radice del repository e impostare la proprietà MSBuild ManagePackageVersionsCentrally
su true
.
È possibile crearlo manualmente oppure usare l'interfaccia della riga di comando dotnet:
dotnet new packagesprops
All'interno si definiscono quindi ognuna delle rispettive versioni del pacchetto necessarie per i progetti usando <PackageVersion />
elementi che definiscono l'ID e la versione del pacchetto.
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>
Per ogni progetto si definisce quindi un <PackageReference />
ma si omette l'attributo Version
poiché la versione verrà ottenuta da un elemento <PackageVersion />
corrispondente.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" />
</ItemGroup>
</Project>
A questo punto si usa la gestione centrale dei pacchetti e si gestiscono le versioni in una posizione centrale.
Regole di gestione pacchetti centrali
Il file Directory.Packages.props
ha una serie di regole relative alla posizione in cui si trova nella directory di un repository e nel relativo contesto. Per semplicità, viene valutato un solo file Directory.Packages.props
per un determinato progetto.
Ciò significa che se nel repository sono presenti più file di Directory.Packages.props
, il file più vicino alla directory del progetto verrà valutato. In questo modo è possibile avere un controllo extra a vari livelli del repository.
Di seguito è riportato un esempio, considerare la struttura di repository seguente:
Repository
|-- Directory.Packages.props
|-- Solution1
|-- Directory.Packages.props
|-- Project1
|-- Solution2
|-- Project2
- Project1 valuterà il file
Directory.Packages.props
nella directoryRepository\Solution1\
e dovrà importare manualmente quello successivo, se necessario.<Project> <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Packages.props, $(MSBuildThisFileDirectory)..))" /> <ItemGroup> <PackageVersion Update="Newtonsoft.Json" Version="12.0.1" /> </ItemGroup> </Project>
- Project2 valuterà il file
Directory.Packages.props
nella directoryRepository\
.
Nota: MSBuild non importerà automaticamente ciascuno Directory.Packages.props
per te, ma solo il primo che si trova più vicino al progetto. Nel caso in cui siano presenti più Directory.Packages.props
, devi importare manualmente quello principale mentre il Directory.Packages.props
radice non verrà importato.
Inizia
Per eseguire l'onboarding completo del repository, seguire questa procedura:
- Creare un nuovo file nella radice del repository denominato
Directory.Packages.props
che dichiara le versioni dei pacchetti definite centralmente e impostare la proprietà MSBuildManagePackageVersionsCentrally
sutrue
. - Dichiara
<PackageVersion />
elementi nel tuoDirectory.Packages.props
. - Dichiarare elementi
<PackageReference />
privi di attributiVersion
nei file di progetto.
Per avere un'idea di come potrebbe apparire la gestione centrale dei pacchetti, fare riferimento al nostro repository di esempi .
Pinning transitivo
È possibile eseguire automaticamente l'override di una versione transitiva del pacchetto anche senza un <PackageReference />
di primo livello esplicito optando per una funzionalità nota come pinning transitivo. In questo modo si promuove una dipendenza transitiva a una dipendenza di livello superiore in modo implicito per conto dell'utente, quando necessario.
Si noti che i downgrade sono consentiti durante il bloccaggio transitivo di un pacchetto. Se si tenta di bloccare un pacchetto a una versione precedente rispetto a quella richiesta dalle dipendenze, il ripristino genererà un errore di NU1109.
È possibile abilitare questa funzionalità impostando la proprietà MSBuild CentralPackageTransitivePinningEnabled
su true
in un progetto o in un Directory.Packages.props
o Directory.Build.props
file di importazione:
<PropertyGroup>
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
Fissaggio transitivo e pacchetto
Quando un pacchetto viene bloccato in modo transitivo, il progetto utilizza una versione superiore a quella richiesta dalle dipendenze. Se crei un pacchetto dal tuo progetto, per garantire che il pacchetto funzioni, NuGet promuoverà le dipendenze bloccate in modo transitivo a dipendenze esplicite nel file nuspec.
Nell'esempio seguente PackageA 1.0.0
ha una dipendenza da 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>
Quando si usa il comando pack per creare un pacchetto, entrambi i pacchetti verranno visualizzati nel gruppo di dipendenze.
<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>
Per questo motivo, l'uso del bloccaggio transitivo deve essere valutato attentamente durante lo sviluppo di una libreria, in quanto potrebbe causare dipendenze non previste.
Sostituzione delle versioni dei pacchetti
È possibile eseguire l'override di una singola versione del pacchetto usando la proprietà VersionOverride
in un elemento <PackageReference />
. Questa operazione esegue l'override di qualsiasi <PackageVersion />
definita centralmente.
<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>
È possibile disabilitare questa funzionalità impostando la proprietà MSBuild CentralPackageVersionOverrideEnabled
su false
in un progetto o in un Directory.Packages.props
o Directory.Build.props
file di importazione:
<PropertyGroup>
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
</PropertyGroup>
Quando questa funzionalità è disabilitata, specificando un VersionOverride
in qualsiasi elemento <PackageReference />
verrà generato un errore in fase di ripristino che indica che la funzionalità è disabilitata.
Disabilitazione della gestione pacchetti centrale
Se si vuole disabilitare la gestione centrale dei pacchetti per un determinato progetto, è possibile disabilitarla impostando la proprietà MSBuild ManagePackageVersionsCentrally
su false
:
<PropertyGroup>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
Riferimenti ai pacchetti globali
Nota
Questa funzionalità è disponibile solo in Visual Studio 2022 17.4 o versione successiva, .NET SDK 7.0.100.preview7 o versione successiva e NuGet 6.4 o versione successiva.
Un riferimento al pacchetto globale viene usato per specificare che un pacchetto verrà usato da ogni progetto in un repository. Sono inclusi i pacchetti che eseguono il controllo delle versioni, estendono la compilazione o qualsiasi altro pacchetto necessario per tutti i progetti. I riferimenti globali ai pacchetti vengono aggiunti al gruppo di elementi PackageReference con i metadati seguenti:
IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"
In questo modo, il pacchetto viene usato solo come dipendenza di sviluppo e impedisce riferimenti ad assembly in fase di compilazione.PrivateAssets="All"
In questo modo si impedisce che i riferimenti globali ai pacchetti vengano prelevati dalle dipendenze downstream.
GlobalPackageReference
elementi dovrebbero essere posizionati nel Directory.Packages.props
per essere utilizzati da ogni progetto in un repository.
<Project>
<ItemGroup>
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.5.109" />
</ItemGroup>
</Project>
Avviso quando si usano più origini di pacchetti
Quando si usa la gestione centrale dei pacchetti, viene visualizzato un avviso di tipo NU1507
se nella configurazione sono definite più origini pacchetto. Per risolvere questo avviso, mappa le origini del pacchetto con mappatura delle origini del pacchetto o specifica un'unica origine del pacchetto.
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.
Nota
La gestione centrale dei pacchetti è in fase di sviluppo attivo. Siamo lieti di provarlo e fornire commenti e suggerimenti che potresti avere in NuGet/Home.