Come impacchettare una libreria .NET portatile con targeting .NET Core?

Come impacchettare una libreria .NET portatile in un modo moderno e generico? Supponiamo di avere un singolo assembly AnyCPU che desidero rendere disponibile a qualsiasi piattaforma .NET che supporti la superficie dell’API .NET Core, ad esempio .NET Framework 4.6 e Universal Windows Platform.

Questa è una serie di domande e risposte che documentano le mie scoperte sull’argomento della moderna creazione di pacchetti NuGet, concentrandosi in particolare sulle modifiche introdotte con NuGet 3. Potresti anche essere interessato ad alcune domande correlate:

  • Come impacchettare una libreria di .NET Framework?
  • Come impacchettare una libreria .NET destinata alla Universal Windows Platform?
  • Come impacchettare una libreria .NET con targeting per .NET Framework e Universal Windows Platform e includere funzionalità specifiche della piattaforma?
  • Come impacchettare una libreria .NET multi-architettura destinata alla piattaforma universale Windows?
  • Come impacchettare una libreria .NET destinata alla Universal Windows Platform e dipende dagli SDK di estensione di Visual Studio?

Questa risposta si basa sui principi utilizzati per il pacchetto di librerie destinate a .NET Framework . Leggi prima la risposta collegata per capire meglio quanto segue.

Per pubblicare la libreria .NET portatile, è necessario creare un pacchetto NuGet con la seguente struttura:

\---lib \---dotnet MyPortableLibrary.dll MyPortableLibrary.pdb MyPortableLibrary.XML 

Tutti e tre i file verranno dalla directory di output build del progetto sotto la configurazione di build Release.

La directory dotnet nella struttura sopra ha un significato speciale: indica a NuGet che i file nella directory devono essere utilizzati su qualsiasi piattaforma compatibile con tutte le dipendenze del pacchetto. Pertanto, il tuo pacchetto è automaticamente utilizzabile su qualsiasi piattaforma .NET che supporti tutte le tue dipendenze (ad es. .NET Core).

Il prossimo passo cruciale è determinare l’elenco delle dipendenze. A causa di un problema di gestione dei pacchetti, non è ansible dichiarare semplicemente una dipendenza su .NET Core stesso (.NET Core è la superficie API condivisa da tutte le piattaforms .NET). Invece, è necessario determinare manualmente ciascuna dipendenza del componente .NET Core e aggiungerla al file nuspec.

Il processo di rilevamento delle dipendenze per i pacchetti .NET Core consiste in due passaggi:

  1. Determinare gli assembly .NET Core a cui fa riferimento la libreria.
  2. Determinare i pacchetti NuGet che contengono questi assembly.

Visual Studio non fornisce le informazioni necessarie. Invece, è necessario creare la libreria e ispezionare il file DLL risultante. Il seguente script PowerShell mostrerà i riferimenti di un assembly .NET:

 Get-ChildItem MyPortableLibrary.dll | % { [Reflection.Assembly]::LoadFile($_.FullName).GetReferencedAssemblies() | % { $_.Name + ".dll" } } 

L’output di questo comando sarà un elenco di nomi assembly, ad esempio:

 System.Runtime.dll System.Resources.ResourceManager.dll System.Numerics.Vectors.dll 

Una volta ottenuto l’elenco, aprire il file project.lock.json nella directory del progetto. Questo file contiene informazioni su tutti i pacchetti NuGet utilizzati dal progetto. Troverete, tra gli altri dati, vari blocchi di JSON come i seguenti:

 "System.Numerics.Vectors/4.1.0": { "dependencies": { "System.Globalization": "[4.0.10, )", "System.Resources.ResourceManager": "[4.0.0, )", "System.Runtime": "[4.0.20, )", "System.Runtime.Extensions": "[4.0.10, )" }, "frameworkAssemblies": [ "mscorlib", "System.Numerics" ], "compile": { "ref/net46/System.Numerics.Vectors.dll": {} }, "runtime": { "lib/net46/System.Numerics.Vectors.dll": {} } }, 

Questo blocco di JSON indica che i file di assembly elencati sotto “compile” sono forniti dal pacchetto elencato nel valore di livello superiore (System.Numerics.Vectors versione 4.1.0). Utilizzare queste informazioni per associare ogni assembly di riferimento a un pacchetto NuGet. Si noti che mentre i nomi di pacchetti e assiemi sono spesso uguali, questo non è sempre il caso!

Per tutti i pacchetti NuGet che non fanno parte di .NET Core, puoi saltare il processo di cui sopra in quanto già conosci il pacchetto esatto su cui hai una dipendenza. La logica di rilevamento delle dipendenze qui descritta è necessaria solo perché non è ansible dichiarare una dipendenza direttamente su .NET Core (il pacchetto Microsoft.NETCore) a causa del problema sopra riportato.

Ora elenca semplicemente tutte le dipendenze nel tuo file nuspec, sulla base del seguente esempio:

    Example.MyPortableLibrary 1.0.0 Firstname Lastname Example of a portable library with NuGet package dependencies.           

Questo è tutto! Il pacchetto risultante è utilizzabile su qualsiasi piattaforma .NET compatibile, come .NET Framework 4.6 o Universal Windows Platform. Ricordarsi di creare la soluzione utilizzando la configurazione di rilascio prima di creare il pacchetto NuGet.

Una libreria di esempio e i relativi file di packaging sono disponibili su GitHub . La soluzione corrispondente a questa risposta è PortableLibrary.

Fai riferimento al blog di Lucian Wischik per approfondire la logica che opera su tali pacchetti NuGet.

Sembra che ci sia stato molto churn sul modo migliore di creare pacchetti di librerie / pacchetti NuGet .NET portatili negli ultimi mesi. Se puoi aspettare un po ‘, ti consigliamo di leggere su .NET Standard . Immo Landwerth ha scritto un post sul blog dettagliato introducendo .NET Standard nel settembre 2016. Il supporto per .NET Standard 2.0 in .NET Core dovrebbe arrivare all’inizio del 2017 , nello stesso periodo di tempo di Visual Studio 2017, che è attualmente in Release Candidate palcoscenico. .NET Standard 2.0 sarà implementato da .NET Framework, .NET Core e Xamarin. Comprenderà anche gli shim di compatibilità per i binari di .NET Framework, che dovrebbero facilitare l’adozione.

Aggiornare:

Oren Novotny ha un post molto informativo su questo argomento: Multi-targeting del mondo: un singolo progetto per dominarli tutti . Discute su .NET Standard e su come target multipli con Visual Studio 2017. Il post del blog è stato pubblicato prima dell’RTM di Visual Studio 2017, ma è molto utile.