Condividi tramite


PackageReference nei file di progetto

I riferimenti ai pacchetti, usando 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 file NuGet.Config (incluse le origini del pacchetto) vengono ancora applicate come illustrato nelle 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 ulteriori informazioni, vedere Pacchetto e ripristino NuGet come obiettivi di MSBuild.

Supporto dei tipi di progetto

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

ASP.NET app che utilizzano il .NET Framework completo includono solo il supporto limitato per PackageReference. I tipi di progetto C++ e JavaScript non sono supportati.

Aggiunta di un riferimento al pacchetto

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 è la stessa di quando si utilizza 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>    

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

PackageReference e sorgenti

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 fluttuanti

Le versioni flottanti 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 delle risorse di dipendenza

È 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 Description Valore predefinito
IncludeAssets Questi asset verranno consumati all
ExcludeAssets Questi asset non verranno utilizzati none
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 all di e none, che devono essere visualizzati da soli:

Value Description
compile Contenuti della cartella lib e controlla se il progetto può essere compilato in base agli assembly all'interno della cartella.
runtime Contenuto della cartella lib e runtimes e controlla se questi assembly verranno copiati dalla directory di output di build.
contentFiles Contenuti della cartella contentfiles
build .props e .targets nella cartella build
buildMultitargeting (4.0).props e .targets nella cartella buildMultitargeting, per il targeting cross-framework
buildTransitive (5.0+).props e .targets nella buildTransitive cartella, per gli asset che passano transitivamente a qualsiasi progetto che lo utilizza. Vedi la pagina delle funzionalità.
analyzers Analizzatori .NET
native Contenuti della cartella native
none Non viene usato alcuno dei valori precedenti.
all 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, poiché build non è incluso con PrivateAssets, le destinazioni e le proprietà fluiranno nel 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 gli obiettivi e le proprietà da Contoso.Utility.UsefulStuff, così come possono farlo i progetti che utilizzano AppLogger.

Note

Quando developmentDependency è impostato su true in un file .nuspec, il pacchetto viene contrassegnato come dipendenza esclusivamente per sviluppo, impedendo 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.

Selezione di più framework

I progetti in stile SDK supportano il multitargeting elencando più valori nella TargetFrameworks proprietà . Quando un progetto è destinato a più framework, il ripristino NuGet produce un grafico delle dipendenze separato per ogni framework e dotnet pack crea un pacchetto con asset specifici del framework per ogni destinazione.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFrameworks>net10.0;netstandard2.0</TargetFrameworks>
  </PropertyGroup>
</Project>

Per ottenere indicazioni dettagliate sulla configurazione di un progetto multi-obiettivo, vedere Supportare più framework .NET nel file di progetto.

Funzionamento dei valori targetFramework

La TargetFramework proprietà in un file di progetto è un nome descrittivo, un alias, che viene tradotto nell'identità canonica del framework. Il SDK di .NET esegue questa conversione impostando il TargetFrameworkMoniker (TFM) e, se applicabile, le proprietà TargetPlatformMoniker.

NuGet usa queste proprietà del moniker — non la stringa TargetFramework — per effettuare controlli di compatibilità dei pacchetti. Ciò significa che il TargetFramework valore stesso può essere qualsiasi stringa, purché le proprietà del moniker siano impostate correttamente.

Per altri dettagli sul meccanismo di aliasing, vedere Valori targetFramework sono alias.

Aggiunta di una condizione PackageReference

È possibile utilizzare una condizione per controllare se è incluso un pacchetto. Le condizioni possono usare qualsiasi variabile MSBuild o una variabile definita nel file targets o props. Attualmente, tuttavia, è supportata solo la TargetFramework variabile .

Supponiamo, ad esempio, che stai puntando a netstandard1.4 e a net452, ma hai una dipendenza applicabile solo per net452. In questo caso non si desidera che un progetto netstandard1.4 che utilizza il pacchetto aggiunga quella dipendenza non necessaria. Per evitarlo, specificare una condizione su 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:

Il risultato dell'applicazione di una condizione a PackageReference con VS2017

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

<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 progetti basati su packages.config, i pacchetti vengono installati in una cartella relativa al file di progetto. Tuttavia, in PackageReference, i pacchetti vengono consumati 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.

Example:

  <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 genera 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 di MSBuild compatibile, preceduto dalla parola Pkg. Per verificare il nome esatto della proprietà generata, esaminare il file generato nuget.g.props.

Alias di PackageReference

In alcuni casi rari, pacchetti diversi conterranno classi nello stesso spazio dei nomi. A partire da NuGet 5.7 e Visual Studio 2019 Update 7, equivalente a ProjectReference, PackageReference supporta Alias. Per impostazione predefinita, non vengono forniti alias. Quando viene specificato un alias, è necessario fare riferimento con un alias a tutti gli assembly provenienti dal pacchetto annotato.

È 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 di NuGet sono codificati e iniziano con NU****. Tutti gli avvisi e gli errori di NuGet sono elencati nella documentazione di riferimento.

NuGet osserva le proprietà di avviso seguenti:

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

Examples:

<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 sopprimere un avviso a livello di tutto il progetto, è consigliabile eseguire le seguenti operazioni:

<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 è in Visual Studio, puoi anche sopprimere 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 NuGet Restore è un insieme di elementi del file di progetto (dipendenze dirette o di primo livello) e l'output è una chiusura completa di tutte le dipendenze del pacchetto, comprese 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. Per esempio:

  • Quando si usano versioni fluttuanti come <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. Per esempio:

    • Giorno 1: se hai 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 avrebbe risolto a 4.1.0 (versione minima più vicina).

    • Giorno 2: viene pubblicata la versione 4.0.0. NuGet troverà ora la corrispondenza esatta e inizierà a risolvere verso la versione 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à del file di blocco impostando la proprietà RestorePackagesWithLockFile MSBuild per il progetto:

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

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

Il formato packages.lock.json è versionato. La versione del formato dipende dalle funzionalità utilizzate, come il fissaggio transitivo nel Central Package Management o la duplicazione dei framework di destinazione efficaci.

Note

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 fittizio vuoto packages.lock.json nella directory radice del progetto.

restore comportamento con il file di blocco

Se per un progetto è presente un file di blocco, NuGet usa questo file di blocco per eseguire restore. NuGet esegue un rapido controllo per verificare se sono state apportate modifiche alle dipendenze del pacchetto come indicato nel file di progetto (o nei file dei progetti dipendenti) e, se non sono state apportate modifiche, vengono ripristinati solo 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 al volo le dipendenze del pacchetto, è possibile farlo impostando il 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 o il ripristino non avrà successo se le dipendenze del pacchetto definite per il progetto sono state aggiornate dopo la creazione del file di blocco.

Bloccare i file e PrunePackageReference

PrunePackageReference modifica le dipendenze di un progetto rimuovendo pacchetti transitivi non necessari. Anche se la rimozione di questi pacchetti non dovrebbe avere un impatto in fase di esecuzione, influirà sui file di blocco. Se si abilita l'eliminazione per un progetto esistente, ogni volta che il file di blocco viene rigenerato, può comportare un minor numero di pacchetti rispetto a prima dell'eliminazione. Il controllo aggiornato del file di blocco che alimenta la modalità bloccata è in grado di riconoscere l'eliminazione, il che significa che se l'eliminazione è stata abilitata in un progetto, il controllo prenderà in considerazione i pacchetti eliminati. Tuttavia, la volta successiva che il file di blocco viene rigenerato, escluderà i pacchetti eliminati, quindi è possibile che venga visualizzato un diff più grande del solito.

Rendere il file di blocco parte del repository di origine

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

Tuttavia, se il progetto è un progetto di libreria che non viene fornito o un progetto di codice comune da cui dipendono altri progetti, non dovresti archiviare il file di blocco come parte del codice sorgente. Non c'è alcun problema nel mantenere il file di blocco, ma durante il ripristino/la compilazione di un progetto che dipende da questo progetto di codice comune, non possono essere utilizzate le dipendenze del pacchetto bloccato per il progetto di codice comune, come elencato nel file di blocco.

Example:

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. Tuttavia, quando ProjectA viene compilato, il relativo file di blocco conterrà una dipendenza dalla 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 Description
-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 flottante 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 un file di blocco specifico del progetto packages.<project_name>.lock.json.

Sistema di risoluzione delle dipendenze NuGet

Il sistema di risoluzione delle dipendenze NuGet segue le quattro regole descritte nel documento sulla risoluzione delle dipendenze.

Per migliorare le prestazioni e la scalabilità dell'operazione di ripristino, l'algoritmo di ripristino è stato riscritto nella versione 6.12. A partire dalla versione 6.12, il nuovo algoritmo di ripristino è abilitato per impostazione predefinita per tutti i progetti PackageReference. Anche se il nuovo algoritmo di ripristino è funzionalmente equivalente a quello precedente, come per qualsiasi software, sono possibili bug. Per ripristinare l'implementazione precedente, impostare la proprietà MSBuild RestoreUseLegacyDependencyResolver su true.

Se riscontri errori di ripristino nella versione 6.12, .NET 9 o 17.12, che non si verificavano nelle versioni precedenti, ti invitiamo a segnalare un problema su GitHub . Eventuali differenze tra gli algoritmi precedenti e quelli nuovi possono avere effetti diversi, ad esempio durante la compilazione o in fase di esecuzione. È anche possibile che le modifiche non comportino errori, ma che versioni diverse dei pacchetti siano ripristinate. Se si ritiene di essere interessati da eventuali modifiche, ecco i passaggi che è possibile eseguire per verificare se le modifiche nell'algoritmo di ripristino NuGet sono la causa radice.

Il ripristino scrive i risultati nella MSBuildProjectExtensionsPath directory, che possono essere confrontati con gli algoritmi nuovi e precedenti per individuare le differenze. In genere, si tratta della cartella obj della tua build. Puoi usare msbuild.exe o dotnet.exe per i passaggi successivi.

  1. Rimuovere la cartella obj per il tuo progetto.

  2. Esegui msbuild -t:restore

  3. Salvare il contenuto del obj in una posizione che indica che è il comportamento del new.

  4. Eseguire msbuild -t:restore -p:RestoreUseLegacyDependencyResolver="true".

  5. Salvare il contenuto del obj in una posizione che indica che è il comportamento del legacy.

  6. Confrontare i file nelle due directory, in particolare project.assets.json.

    Gli strumenti che possono evidenziare le differenze sono particolarmente utili per questo(ad esempio, in Visual Studio Code, aprire entrambi i file e usare il pulsante destro del mouse su "seleziona per confrontare" e "confrontare con selezionato").

Se si segue il metodo precedente, dovrebbe esserci esattamente 1 discrepanza tra i project.assets.json file.

      "projectStyle": "PackageReference",
+     "restoreUseLegacyDependencyResolver": true,
      "fallbackFolders": [

Se sono presenti altre differenze, segnalare un problema in GitHub con tutti i dettagli.

AssetTargetFallback

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

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

Fare riferimento alla tabella seguente per esempi di come AssetTargetFallback influisce sulla compatibilità.

Framework del progetto AssetTargetFallback Framework per pacchetti Result
.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, errore 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 desideri sovrascrivere i valori esistenti, puoi omettere $(AssetTargetFallback) anziché aggiungere ai valori attuali AssetTargetFallback.

Note

Se si utilizza un progetto basato su .NET SDK, i valori appropriati vengono configurati e non è necessario impostarli manualmente.

$(PackageTargetFallback) era una funzionalità precedente che aveva tentato di risolvere questa sfida, ma è fondamentalmente difettosa e non dovrebbe essere utilizzata. Per eseguire la migrazione da $(PackageTargetFallback) a $(AssetTargetFallback), è sufficiente modificare il nome della proprietà.

Multitargeting con framework ridondanti

Questa funzionalità richiede NuGet 7.6 / .NET SDK 10.0.300 o versione successiva.

Poiché TargetFramework i valori sono alias, più alias possono risolversi nel stesso framework efficace. A partire da NuGet 7.6 / .NET SDK 10.0.300, NuGet e .NET SDK supportano questo scenario.

Ciò consente casi d'uso come:

  • Compilazioni multi-RID: consente di compilare assembly specifici della piattaforma da un singolo progetto.

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFrameworks>net10.0;linux;ios</TargetFrameworks>
      </PropertyGroup>
    
      <PropertyGroup Condition="'$(TargetFramework)' == 'linux' OR '$(TargetFramework)' == 'ios' OR '$(TargetFramework)' == 'net10.0'">
        <TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
        <TargetFrameworkVersion>v10.0</TargetFrameworkVersion>
        <TargetFrameworkMoniker>.NETCoreApp,Version=v10.0</TargetFrameworkMoniker>
      </PropertyGroup>
    </Project>
    
  • Benchmarking di diverse versioni di un pacchetto

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <TargetFrameworks>benchmark7.0;benchmark8.0</TargetFrameworks>
      </PropertyGroup>
    
      <!-- Frameworks omitted for brevity-->
    
      <ItemGroup>
        <PackageReference Include="BenchmarkDotNet" Version="0.13.9" />
        <PackageReference Include="Contoso.FastLibrary" Version="7.0" Condition="'$(TargetFramework)' == 'benchmark7.0' "/>
        <PackageReference Include="Contoso.FastLibrary" Version="8.0" Condition="'$(TargetFramework)' == 'benchmark8.0' "/>
      </ItemGroup>
    </Project>
    

Pacchetto

Un pacchetto NuGet può contenere solo un set di output di compilazione e un gruppo di dipendenze per ogni framework efficace. Quando si impacchetta un progetto con framework effettivi duplicati, è necessario indicare a NuGet quale alias contribuisce a queste risorse, altrimenti il pacchetto solleva NU5051. Vedere NU5051 per i passaggi e gli esempi di risoluzione.

Riferimenti al progetto

Quando un progetto fa riferimento a un altro progetto con più alias che si risolvono nello stesso framework, NuGet usa il nome dell'alias come tiebreaker. Se il progetto di riferimento ha un alias con lo stesso nome di uno nel progetto a cui si fa riferimento, tale alias è preferibile. Se non sono presenti nomi corrispondenti e più candidati, NuGet segnala un errore.

Limitazioni

  • Solo i progetti in stile SDK supportano framework effettivi duplicati.
  • Gli alias che contengono caratteri separatori di percorso (/ o \) vengono bloccati.
  • L'interfaccia utente di Gestione pacchetti di Visual Studio non dispone di un supporto speciale per i framework duplicati, ma è possibile gestire i pacchetti modificando il file di progetto direttamente o usando l'interfaccia della dotnet riga di comando.

PrunePackageReference

Il runtime .NET è in continua evoluzione, con miglioramenti delle prestazioni e nuove API ogni versione. Le nuove funzionalità aggiunte a .NET vengono fornite anche come pacchetti, in modo che gli sviluppatori che usano framework di destinazione meno recenti possano usare la libreria, ad esempio System.Text.Json. Questo può spesso portare a un System.Text.Json 8.0.0 in un progetto destinato a .NET 9 o .NET 8. Questa dipendenza non è necessaria e la risoluzione dei conflitti di compilazione non userà l'assembly proveniente dal pacchetto perché è già disponibile in .NET Runtime. A partire da NuGet versione 6.13 e .NET SDK 9.0.200, PrunePackageReference abilita l'eliminazione di questi pacchetti in fase di ripristino per i progetti basati su .NET SDK. La prima iterazione dell'eliminazione interessa solo i pacchetti transitivi, ma a partire da .NET SDK 10, l'eliminazione dei pacchetti influisce anche sui pacchetti diretti.

L'eliminazione dei pacchetti è disponibile come funzionalità opzionale con .NET 9 SDK ed è abilitata per impostazione predefinita per tutti i framework di un progetto destinato a >= .NET 10.0 nel .NET 10 SDK.

L'eliminazione del pacchetto è disponibile solo con il sistema di risoluzione delle dipendenze predefinito come rilasciato nella versione 6.12.

Specifica PrunePackageReference

L'elenco dei pacchetti da eliminare viene definito con l'elemento PrunePackageReference.

Attributes Description
Version Specifica la versione massima da eliminare. 1.0.0 significa che tutti i pacchetti fino alla versione 1.0.0 verranno eliminati. Per 1.0.0, 0.9.0 e 1.0.0 verranno eliminati, ma non 1.0.1.

Per modificare il comportamento di eliminazione, è possibile utilizzare le proprietà seguenti.

PropertyName Description
RestoreEnablePackagePruning Abilita l'eliminazione dei pacchetti per i pacchetti specificati con PrunePackageReference. Questa proprietà è per framework di destinazione e i valori validi sono true e false. Le impostazioni predefinite possono variare in base a .NET SDK, come definito in precedenza.

Il .NET SDK predefinisce per te l'elenco dei pacchetti da rimuovere. Tale elenco è basato sui framework condivisi specificati nel progetto. Vengono considerati solo i riferimenti diretti al framework e i dati di potatura non verranno aggiunti per i framework che vengono inseriti tramite pacchetti.

Funzionamento di PrunePackageReference

Quando si specifica un pacchetto da eliminare durante il ripristino, viene rimosso dal grafico delle dipendenze. Quando un pacchetto viene eliminato, è presente un messaggio, visibile con dettagli dettagliati, che indica che il pacchetto è stato rimosso per il framework di destinazione specificato.

Per i pacchetti transitivi, ovvero le dipendenze di altri pacchetti o progetti, i pacchetti non vengono scaricati e non vengono visualizzati in alcun output di NuGet.

Per i pacchetti diretti, PrivateAssets='all' e IncludeAssets='none' vengono applicati in modo implicito.

  • IncludeAssets='none' garantisce che gli assembly di questo pacchetto non vengano usati durante la compilazione. Prima che la potatura esistesse, la risoluzione dei conflitti durante la compilazione garantiva che gli assembly della piattaforma venissero preferiti rispetto a quelli provenienti dai pacchetti.
  • PrivateAssets='all' garantisce che i pacchetti non siano inclusi nei pacchetti o tramite riferimenti al progetto.

Example:

Un progetto simile al seguente:

  <PropertyGroup>
    <TargetFrameworks>net9.0;netstandard2.0</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Text.Json" Version="9.0.4" />
  </ItemGroup>

avrà un nuspec con le seguenti dipendenze:

<dependencies>
    <group targetFramework=".NETFramework4.7.2">
        <dependency id="System.Text.Json" version="9.0.4" />
    </group>
    <group targetFramework="net9.0">
    </group>
</dependencies>

Quando un packageReference diretto può essere rimosso completamente dal progetto e uno dei framework di progetto è .NET 10 o versione successiva, NU1510 verrà generato chiedendo di rimuovere il pacchetto. Seguendo questo suggerimento si ridurrà la complessità del grafico del progetto.

La tabella seguente riepiloga tutti i comportamenti di eliminazione dei pacchetti.

Eliminazione delle dipendenze Behavior
Corrisponde all'ID di un pacchetto transitivo proveniente da un altro pacchetto Prune
Corrisponde all'ID di un pacchetto transitivo proveniente da un altro progetto Prune
Corrisponde all'ID di un PackageReference diretto Applicate PrivateAssets='all' e IncludeAssets='none' e generare l'avviso NU1510 quando il pacchetto può essere rimosso da tutti i framework e il progetto punta a .NET 10.
Corrisponde all'ID di un ProjectReference Non eliminare e generare l'avviso NU1511 quando il progetto è destinato a .NET 10

Applicazioni PrunePackageReference

I vantaggi della riduzione dei pacchetti sono duplici:

  • Vantaggi delle prestazioni, grazie alla riduzione del numero di pacchetti all'interno di un grafico delle dipendenze
  • Riduzione dei falsi positivi per scanner di componenti come NuGetAudit

L'eliminazione è particolarmente utile quando si controllano i pacchetti con NuGetAuditMode impostato su all. Se utilizzi .NET 9, ti consigliamo di provare la potatura impostando [l'opzione] su RestoreEnablePackagePruning e true.