PackageReference nei file di progetto

I riferimenti ai pacchetti, usando <PackageReference> gli elementi MSBuild, specificano le dipendenze del pacchetto NuGet direttamente all'interno dei file di progetto, anziché avere un file separato packages.config . L'uso di PackageReference non influisce su altri aspetti di NuGet; Ad esempio, le impostazioni nei NuGet.Config file (incluse le origini del pacchetto) vengono ancora applicate come illustrato in Configurazioni NuGet comuni.

Con PackageReference è anche possibile usare le condizioni di MSBuild per scegliere i riferimenti ai pacchetti per ogni framework di destinazione o altri raggruppamenti. Consente anche un controllo più capillare delle dipendenze e del flusso del contenuto. (Per altri dettagli, vedere Pack e restore di NuGet come destinazioni MSBuild .)

Supporto dei tipi di progetto

Per impostazione predefinita, PackageReference viene usato per i progetti .NET Core, i progetti .NET Standard e i progetti UWP destinati a Windows 10 Build 15063 (Creators Update) e versioni successive, con l'eccezione dei progetti UWP C++. I progetti .NET Framework supportano PackageReference, ma usano attualmente packages.config per impostazione predefinita. Per usare PackageReference, eseguire la migrazione delle dipendenze da packages.config nel file di progetto e quindi rimuovere packages.config.

Le app ASP.NET destinate a .NET Framework includono solo un supporto limitato per PackageReference. I tipi di progetto C++ e JavaScript non sono supportati.

Aggiunta di PackageReference

Aggiungere una dipendenza nel file di progetto usando la sintassi seguente:

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
    <!-- ... -->
</ItemGroup>

Controllo della versione della dipendenza

La convenzione per specificare la versione di un pacchetto è uguale quando si usa packages.config:

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
    <!-- ... -->
</ItemGroup>

Nell'esempio precedente, 3.6.0 indica qualsiasi versione >=3.6.0 con preferenza per la versione più bassa, come descritto in Controllo delle versioni dei pacchetti.

Uso di PackageReference per un progetto senza dipendenze del pacchetto

Avanzato: se non si hanno pacchetti installati in un progetto (nessun PackageReference nel file di progetto e nessun file packages.config), ma si vuole ripristinare il progetto con stile PackageReference, è possibile impostare una proprietà del progetto RestoreProjectStyle su PackageReference nel file di progetto.

<PropertyGroup>
    <!--- ... -->
    <RestoreProjectStyle>PackageReference</RestoreProjectStyle>
    <!--- ... -->
</PropertyGroup>    

Questa opzione può essere utile se si fa riferimento a progetti con stile PackageReference (progetti con stile SDK o csproj esistenti). In questo modo, sarà possibile fare riferimento "in modo transitivo" dal progetto ai pacchetti a cui fanno riferimento tali progetti.

PackageReference e origini

Nei progetti PackageReference le versioni delle dipendenze transitive vengono risolte in fase di ripristino. Di conseguenza, nei progetti PackageReference tutte le origini devono essere disponibili per tutti i ripristini.

Versioni mobili

Le versioni mobili sono supportate con PackageReference:

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.*" />
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0-beta.*" />
    <!-- ... -->
</ItemGroup>

Controllo degli asset delle dipendenze

È possibile che si usi una dipendenza esclusivamente come strumento di sviluppo e che non si voglia esporla nei progetti che utilizzano il pacchetto. In questo scenario, è possibile usare i metadati PrivateAssets per controllare questo comportamento.

<ItemGroup>
    <!-- ... -->

    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0">
        <PrivateAssets>all</PrivateAssets>
    </PackageReference>

    <!-- ... -->
</ItemGroup>

I tag di metadati seguenti controllano gli asset delle dipendenze:

Tag Descrizione Valore predefinito
IncludeAssets Questi asset verranno utilizzati tutto
ExcludeAssets Questi asset non verranno utilizzati Nessuno
PrivateAssets Questi asset verranno utilizzati, ma non verranno trasferiti al progetto padre contentfiles;analyzers;build

I valori consentiti per questi tag sono i seguenti, con più valori separati da un punto e virgola, ad eccezione di all e none che devono essere usati da soli:

Valore Descrizione
compile Contenuti della cartella lib. Controlla se il progetto può essere compilato in base agli assembly nella cartella
runtime Contenuti delle cartelle lib e runtimes. Controlla se questi assembly verranno copiati nella directory di output build
contentFiles Contenuto della cartella contentfiles
build .props e .targets nella cartella build
buildMultitargeting (4.0).props e .targets nella cartella buildMultitargeting per più framework di destinazione
buildTransitive (5.0 +).props e .targets nella cartella buildTransitive per gli asset che si propagano in modo transitivo a qualsiasi progetto che gli utilizza. Vedere la pagina delle funzionalità.
analyzers Analizzatori .NET
nativi Contenuto della cartella native
Nessuno Non viene usato alcuno dei valori precedenti.
tutto Tutti i valori precedenti (ad eccezione di none)
<ItemGroup>
    <!-- ... -->
    <!-- Everything except the content files will be consumed by the project -->
    <!-- Everything except content files and analyzers will flow to the parent project-->
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0">
        <IncludeAssets>all</IncludeAssets> <!-- Default is `all`, can be omitted-->
        <ExcludeAssets>contentFiles</ExcludeAssets>
        <PrivateAssets>contentFiles;analyzers</PrivateAssets>
    </PackageReference>
    <!-- ... -->
    <!-- Everything except the compile will be consumed by the project -->
    <!-- Everything except contentFiles will flow to the parent project-->
    <PackageReference Include="Contoso.Utility.SomeOtherUsefulStuff" Version="3.6.0">
        <ExcludeAssets>compile</ExcludeAssets>
        <PrivateAssets>contentFiles</PrivateAssets>
    </PackageReference>
    <!-- ... -->
</ItemGroup>

Si noti che dato che build non è incluso in PrivateAssets, le destinazioni e le proprietà verranno trasferite al progetto padre. Si consideri, ad esempio, che il riferimento precedente viene usato in un progetto che compila un pacchetto NuGet chiamato AppLogger. AppLogger può utilizzare le destinazioni e le proprietà da Contoso.Utility.UsefulStuff, analogamente ai progetti che utilizzano AppLogger.

Nota

Quando developmentDependency è impostato su true in un file .nuspec, un pacchetto viene contrassegnato come dipendenza solo per lo sviluppo, impedendo in tal modo che il pacchetto venga incluso come dipendenza in altri pacchetti. Con PackageReference (NuGet 4.8 +), questo flag indica anche che gli asset in fase di compilazione verranno esclusi dalla compilazione. Per altre informazioni, vedere Supporto di DevelopmentDependency per PackageReference.

Aggiunta di una condizione PackageReference

È possibile usare una condizione per controllare se un pacchetto è incluso e le condizioni possono usare qualsiasi variabile di MSBuild o una variabile definita nel file delle destinazioni o delle proprietà. Tuttavia, attualmente è supportata solo la variabile TargetFramework.

Ad esempio, si supponga di usare netstandard1.4 e net452 come destinazione, ma di avere una dipendenza applicabile solo per net452. In questo caso non si vuole che un progetto netstandard1.4 che utilizza il pacchetto aggiunta tale dipendenza non necessaria. Per evitarlo, è possibile specificare una condizione in PackageReference come segue:

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Newtonsoft.Json" Version="9.0.1" Condition="'$(TargetFramework)' == 'net452'" />
    <!-- ... -->
</ItemGroup>

Un pacchetto compilato con questo progetto indica che Newtonsoft.Json è incluso come dipendenza solo per una destinazione net452:

The result of applying a Condition on PackageReference with VS2017

Le condizioni possono essere applicate anche al livello ItemGroup e verranno applicate a tutti gli elementi PackageReference figlio:

<ItemGroup Condition = "'$(TargetFramework)' == 'net452'">
    <!-- ... -->
    <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
    <PackageReference Include="Contoso.Utility.UsefulStuff" Version="3.6.0" />
    <!-- ... -->
</ItemGroup>

GeneratePathProperty

Questa funzionalità è disponibile con NuGet 5.0 o versione successiva e con Visual Studio 2019 16.0 o versione successiva.

A volte è consigliabile fare riferimento ai file in un pacchetto da una destinazione MSBuild. Nei packages.config progetti basati, i pacchetti vengono installati in una cartella relativa al file di progetto. Tuttavia, in PackageReference, i pacchetti vengono utilizzati dalla cartella global-packages , che può variare da computer a computer.

Per colmare tale gap, NuGet ha introdotto una proprietà che punta alla posizione da cui verrà utilizzato il pacchetto.

Esempio:

  <ItemGroup>
      <PackageReference Include="Some.Package" Version="1.0.0" GeneratePathProperty="true" />
  </ItemGroup>

  <Target Name="TakeAction" AfterTargets="Build">
    <Exec Command="$(PkgSome_Package)\something.exe" />
  </Target>

NuGet genererà inoltre automaticamente le proprietà per i pacchetti contenenti una cartella degli strumenti.

  <ItemGroup>
      <PackageReference Include="Package.With.Tools" Version="1.0.0" />
  </ItemGroup>

  <Target Name="TakeAction" AfterTargets="Build">
    <Exec Command="$(PkgPackage_With_Tools)\tools\tool.exe" />
  </Target>

Le proprietà di MSBuild e le identità dei pacchetti non hanno le stesse restrizioni, pertanto l'identità del pacchetto deve essere modificata in un nome descrittivo di MSBuild, preceduto dalla parola Pkg. Per verificare il nome esatto della proprietà generata, esaminare il file nuget.g.props generato.

Alias PackageReference

In alcune rare istanze pacchetti diversi conterranno classi nello stesso spazio dei nomi. A partire da NuGet 5.7 & Visual Studio 2019 Update 7, equivalente a ProjectReference, PackageReference supporta Aliases. Per impostazione predefinita, non vengono forniti alias. Quando si specifica un alias, è necessario fare riferimento a tutti gli assembly provenienti dal pacchetto con annotazioni con un alias.

È possibile esaminare l'utilizzo di esempio in NuGet\Samples

Nel file di progetto specificare gli alias come segue:

  <ItemGroup>
    <PackageReference Include="NuGet.Versioning" Version="5.8.0" Aliases="ExampleAlias" />
  </ItemGroup>

e nel codice usarlo come segue:

extern alias ExampleAlias;

namespace PackageReferenceAliasesExample
{
...
        {
            var version = ExampleAlias.NuGet.Versioning.NuGetVersion.Parse("5.0.0");
            Console.WriteLine($"Version : {version}");
        }
...
}

Avvisi ed errori nuGet

Questa funzionalità è disponibile con NuGet 4.3 o versione successiva e con Visual Studio 2017 15.3 o versione successiva.

Per molti scenari di pacchetto e ripristino, tutti gli avvisi e gli errori NuGet vengono codificati e iniziano con NU****. Tutti gli avvisi e gli errori nuGet sono elencati nella documentazione di riferimento .

NuGet osserva le proprietà di avviso seguenti:

  • TreatWarningsAsErrors, considera tutti gli avvisi come errori
  • WarningsAsErrors, trattare avvisi specifici come errori
  • NoWarn, nascondere avvisi specifici, a livello di progetto o a livello di pacchetto.

Esempi:

<PropertyGroup>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
...
<PropertyGroup>
    <WarningsAsErrors>$(WarningsAsErrors);NU1603;NU1605</WarningsAsErrors>
</PropertyGroup>
...
<PropertyGroup>
    <NoWarn>$(NoWarn);NU5124</NoWarn>
</PropertyGroup>
...
<ItemGroup>
    <PackageReference Include="Contoso.Package" Version="1.0.0" NoWarn="NU1605" />
</ItemGroup>

Eliminazione degli avvisi nuGet

Sebbene sia consigliabile risolvere tutti gli avvisi NuGet durante le operazioni di pack e ripristino, in determinate situazioni è necessario eliminarli. Per eliminare un progetto di avviso a livello di avviso, è consigliabile eseguire le operazioni seguenti:

<PropertyGroup>
    <PackageVersion>5.0.0</PackageVersion>
    <NoWarn>$(NoWarn);NU5104</NoWarn>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="Contoso.Package" Version="1.0.0-beta.1"/>
</ItemGroup>

A volte gli avvisi si applicano solo a un determinato pacchetto nel grafico. È possibile scegliere di eliminare l'avviso in modo più selettivo aggiungendo un oggetto NoWarn nell'elemento PackageReference.

<PropertyGroup>
    <PackageVersion>5.0.0</PackageVersion>
</PropertyGroup>
<ItemGroup>
    <PackageReference Include="Contoso.Package" Version="1.0.0-beta.1" NoWarn="NU1603" />
</ItemGroup>

Eliminazione degli avvisi del pacchetto NuGet in Visual Studio

Quando si usa Visual Studio, è anche possibile eliminare gli avvisi tramite l'IDE.

Blocco delle dipendenze

Questa funzionalità è disponibile con NuGet 4.9 o versione successiva e con Visual Studio 2017 15.9 o versione successiva.

L'input per il ripristino NuGet è un set di elementi del file di PackageReference progetto (dipendenze dirette o di primo livello) e l'output è una chiusura completa di tutte le dipendenze del pacchetto, incluse le dipendenze transitive. NuGet prova a produrre sempre la stessa chiusura completa di dipendenze del pacchetto se l'elenco PackageReference di input non è stato modificato. Esistono tuttavia alcuni scenari in cui non è possibile farlo. Ad esempio:

  • Quando si usano versioni mobili, ad esempio <PackageReference Include="My.Sample.Lib" Version="4.*"/>. Anche se in questo caso la finalità è il passaggio alla versione più recente a ogni ripristino dei pacchetti, esistono scenari in cui gli utenti richiedono che il grafo venga bloccato su una determinata versione più recente e passi a una versione successiva, se disponibile, in caso di movimento esplicito.

  • Viene pubblicata una versione più recente del pacchetto che risponde ai requisiti di versione di PackageReference. ad esempio

    • Giorno 1: si è specificato <PackageReference Include="My.Sample.Lib" Version="4.0.0"/>, ma le versioni disponibili nei repository NuGet erano 4.1.0, 4.2.0 e 4.3.0. In questo caso, NuGet restituirebbe 4.1.0 (la versione minima più vicina)

    • Giorno 2: viene pubblicata la versione 4.0.0. NuGet troverà ora la corrispondenza esatta e inizierà a restituire 4.0.0

  • Una versione del pacchetto specifica viene rimossa dal repository. Anche se nuget.org non consente eliminazioni di pacchetti, non tutti i repository di pacchetti hanno questo vincolo. NuGet trova di conseguenza la corrispondenza migliore quando non può restituire la versione eliminata.

Abilitazione del file di blocco

Per rendere persistente la chiusura completa delle dipendenze del pacchetto, è possibile acconsentire esplicitamente alla funzionalità di file di blocco impostando la proprietà MSBuild RestorePackagesWithLockFile per il progetto:

<PropertyGroup>
    <!--- ... -->
    <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
    <!--- ... -->
</PropertyGroup>    

Se questa proprietà viene impostata, il ripristino NuGet genererà un file di blocco, il file packages.lock.json, nella directory radice del progetto, che elenca tutte le dipendenze del pacchetto.

Nota

Quando nella directory radice di un progetto è presente il file packages.lock.json, il file di blocco viene sempre usato con il ripristino anche se la proprietà RestorePackagesWithLockFile non è impostata. Un altro modo per acconsentire esplicitamente a questa funzionalità è quindi quello di creare un file packages.lock.json fittizio vuoto nella directory radice del progetto.

Comportamento di restore con il file di blocco

Se un file di blocco è presente per il progetto, NuGet lo usa per eseguire restore. NuGet esegue un rapido controllo per verificare se sono state apportate modifiche alle dipendenze del pacchetto indicate nel file di progetto (o nei file dei progetti dipendenti) e, se non sono presenti modifiche, si limita a ripristinare i pacchetti indicati nel file di blocco. Non viene eseguita alcuna rivalutazione delle dipendenze del pacchetto.

Se NuGet rileva una modifica nelle dipendenze definite indicate nei file di progetto, rivaluta il grafo del pacchetto e aggiorna il file di blocco in modo da riflettere la nuova chiusura del pacchetto per il progetto.

Per CI/CD e altri scenari in cui non si vogliono modificare le dipendenze del pacchetto immediatamente, è possibile farlo impostando lockedmode su true:

Per dotnet.exe, eseguire:

> dotnet.exe restore --locked-mode

Per msbuild.exe, eseguire:

> msbuild.exe -t:restore -p:RestoreLockedMode=true

È anche possibile impostare questa proprietà MSBuild condizionale nel file di progetto:

<PropertyGroup>
    <!--- ... -->
    <RestoreLockedMode>true</RestoreLockedMode>
    <!--- ... -->
</PropertyGroup> 

Se la modalità di blocco è true, verranno ripristinati i pacchetti esatti elencati nel file di blocco. Il ripristino avrà invece esito negativo se le dipendenze del pacchetto definite per il progetto sono state aggiornate dopo la creazione del file di blocco.

Rendere il file di blocco parte del repository di origine

Se si compila un'applicazione, un file eseguibile e il progetto in questione sono alla inizio della catena di dipendenze, quindi archiviare il file di blocco nel repository di codice sorgente in modo che NuGet possa usarlo durante il ripristino.

Se tuttavia il progetto è un progetto libreria che non viene distribuito o un progetto di codice comune da cui dipendono altri progetti, non è consigliabile archiviare il file di blocco come parte del codice sorgente. È possibile mantenere il file di blocco, ma le dipendenze del pacchetto bloccato per il progetto di codice comune, elencate nel file di blocco, non possono essere usate durante il ripristino o la compilazione di un progetto che dipende da questo progetto di codice comune.

Ad esempio:

ProjectA
  |------> PackageX 2.0.0
  |------> ProjectB
             |------>PackageX 1.0.0

Se ProjectA ha una dipendenza da PackageX versione 2.0.0 e fa anche riferimento a ProjectB che dipende da PackageX versione 1.0.0, il file di blocco per ProjectB elencherà una dipendenza da PackageX versione 1.0.0. Quando tuttavia ProjectA viene compilato, il file di blocco conterrà una dipendenza da PackageX versione 2.0.0 e non1.0.0 come elencato nel file di blocco per ProjectB. Di conseguenza, il file di blocco di un progetto di codice comune ha poca influenza sui pacchetti risolti per i progetti che dipendono da esso.

Estendibilità di file di blocco

È possibile controllare diversi comportamenti di ripristino con file di blocco, come descritto di seguito:

opzione NuGet.exe opzione dotnet Opzione MSBuild equivalente Descrizione
-UseLockFile --use-lock-file RestorePackagesWithLockFile Acconsente esplicitamente all'utilizzo di un file di blocco.
-LockedMode --locked-mode RestoreLockedMode Abilita la modalità di blocco per il ripristino. Ciò è utile negli scenari CI/CD in cui si desidera compilare compilazioni ripetibili.
-ForceEvaluate --force-evaluate RestoreForceEvaluate Questa opzione è utile con i pacchetti con la versione mobile definita nel progetto. Per impostazione predefinita, il ripristino NuGet non aggiornerà automaticamente la versione del pacchetto a ogni ripristino, a meno che non si esegua il ripristino con questa opzione.
-LockFilePath --lock-file-path NuGetLockFilePath Definisce un percorso di file di blocco personalizzato per un progetto. Per impostazione predefinita, NuGet supporta packages.lock.json nella directory radice. Se nella stessa directory sono presenti più progetti, NuGet supporta il file di blocco packages.<project_name>.lock.json specifico del progetto

AssetTargetFallback

La AssetTargetFallback proprietà consente di specificare versioni aggiuntive del framework compatibili per i progetti a cui fa riferimento il progetto e i pacchetti NuGet utilizzati dal progetto.

Se si specifica una dipendenza del pacchetto usando PackageReference ma tale pacchetto non contiene asset compatibili con il framework di destinazione dei progetti, la AssetTargetFallback proprietà entra in gioco. La compatibilità del pacchetto a cui si fa riferimento viene ricontrollata usando ogni framework di destinazione specificato in AssetTargetFallback. Quando viene fatto riferimento a o projectpackage tramite AssetTargetFallback, verrà generato l'avviso NU1701 .

Per esempi di AssetTargetFallback impatto sulla compatibilità, vedere la tabella seguente.

Framework del progetto AssetTargetFallback Framework di pacchetto Risultato
.NET Framework 4.7.2 .NET Standard 2.0 .NET Standard 2.0
App .NET Core 3.1 .NET Standard 2.0, .NET Framework 4.7.2 .NET Standard 2.0
App .NET Core 3.1 .NET Framework 4.7.2 Incompatibile, non eseguire l'operazione con NU1202
App .NET Core 3.1 net472; net471 .NET Framework 4.7.2 .NET Framework 4.7.2 con NU1701

È possibile specificare più framework usando ; come delimitatore. Per aggiungere un framework di fallback, è possibile eseguire le operazioni seguenti:

<AssetTargetFallback Condition=" '$(TargetFramework)'=='netcoreapp3.1' ">
    $(AssetTargetFallback);net472;net471
</AssetTargetFallback>

Se si desidera sovrascrivere, è possibile evitare $(AssetTargetFallback) di aggiungere ai valori esistenti AssetTargetFallback .

Nota

Se si usa un progetto basato su .NET SDK, i valori appropriati $(AssetTargetFallback) vengono configurati e non è necessario impostarli manualmente.

$(PackageTargetFallback) è stata una funzionalità precedente che ha tentato di risolvere questa sfida, ma è fondamentalmente interrotta e non deve essere usata. Per eseguire la migrazione da $(PackageTargetFallback) a $(AssetTargetFallback), è sufficiente modificare il nome della proprietà.