Condividi tramite


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 directory Repository\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 directory Repository\.

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:

  1. Creare un nuovo file nella radice del repository denominato Directory.Packages.props che dichiara le versioni dei pacchetti definite centralmente e impostare la proprietà MSBuild ManagePackageVersionsCentrally su true.
  2. Dichiara <PackageVersion /> elementi nel tuo Directory.Packages.props.
  3. Dichiarare elementi <PackageReference /> privi di attributi Version 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.