Librerie di classi portabili

Suggerimento

Le librerie di classi portabili sono considerate deprecate nelle versioni più recenti di Visual Studio. Anche se è ancora possibile aprire, modificare e compilare le librerie CAL, per i nuovi progetti è consigliabile usare le librerie .NET Standard per accedere a una superficie di attacco API più ampia.

Un componente chiave della compilazione di applicazioni multipiattaforma è in grado di condividere il codice in vari progetti specifici della piattaforma. Tuttavia, questo è complicato dal fatto che le diverse piattaforme usano spesso un sottoinsieme diverso della libreria di classi di base .NET (BCL) e quindi vengono effettivamente compilate in un profilo di libreria .NET Core diverso. Ciò significa che ogni piattaforma può usare solo librerie di classi destinate allo stesso profilo in modo che sembrino richiedere progetti di libreria di classi separati per ogni piattaforma.

Esistono tre approcci principali alla condivisione del codice che risolva questo problema: progetti .NET Standard, progetti di asset condivisi e progetti PCL (Portable Class Library).

  • I progetti .NET Standard sono l'approccio preferito per la condivisione del codice .NET, altre informazioni sui progetti .NET Standard e Xamarin.
  • I progetti di asset condivisi usano un singolo set di file e offrono un modo rapido e semplice in cui condividere il codice all'interno di una soluzione e in genere usa direttive di compilazione condizionale per specificare i percorsi di codice per varie piattaforme che lo useranno (per altre informazioni vedere l'articolo Progetti condivisi).
  • I progetti PCL hanno come destinazione profili specifici che supportano un set noto di classi/funzionalità BCL. Tuttavia, il lato inferiore della libreria di classi portabile è che spesso richiedono un'architettura aggiuntiva per separare codice specifico del profilo nelle proprie librerie.

Questa pagina illustra come creare un progetto PCL destinato a un profilo specifico, a cui possono quindi fare riferimento più progetti specifici della piattaforma.

Che cos'è una libreria di classi portabile?

Quando si crea un progetto di applicazione o un progetto di libreria, la DLL risultante è limitata all'uso della piattaforma specifica per cui viene creata. In questo modo si impedisce di scrivere un assembly per un'app di Windows e quindi di usarlo di nuovo in Xamarin.iOS e Xamarin.Android.

Quando si crea una libreria di classi portabile, tuttavia, è possibile scegliere una combinazione di piattaforme in cui si vuole eseguire il codice. Le scelte di compatibilità effettuate durante la creazione di una libreria di classi portabile vengono convertite in un identificatore "Profilo", che descrive le piattaforme supportate dalla libreria.

La tabella seguente illustra alcune delle funzionalità che variano in base alla piattaforma .NET. Per scrivere un assembly PCL che garantisce l'esecuzione su dispositivi/piattaforme specifici, è sufficiente scegliere il supporto necessario quando si crea il progetto.

Funzionalità .NET Framework App UWP Silverlight Windows Phone Xamarin
Memoria centrale S Y Y Y S
LINQ S Y Y Y S
IQueryable S Y S 7.5+ Y
Serializzazione S Y Y Y S
Annotazioni dei dati 4.0.3 + S Y S

La colonna Xamarin riflette il fatto che Xamarin.iOS e Xamarin.Android supportano tutti i profili forniti con Visual Studio e la disponibilità di funzionalità in tutte le librerie create sarà limitata solo dalle altre piattaforme che si sceglie di supportare.

Sono inclusi i profili che sono combinazioni di:

  • .NET 4 o .NET 4.5
  • Silverlight 5
  • Windows Phone 8
  • App UWP

Per altre informazioni sulle funzionalità dei diversi profili, vedere il riepilogo del profilo PCL di un altro membro della community che include informazioni sul framework supportate e altre note.

Vantaggi

  1. Condivisione centralizzata del codice: scrivere e testare il codice in un singolo progetto che può essere utilizzato da altre librerie o applicazioni.
  2. Le operazioni di refactoring influiscono su tutto il codice caricato nella soluzione (la libreria di classi portabile e i progetti specifici della piattaforma).
  3. Il progetto PCL può essere facilmente referenziato da altri progetti in una soluzione oppure l'assembly di output può essere condiviso per altri utenti a cui fare riferimento nelle proprie soluzioni.

Svantaggi

  1. Poiché la stessa libreria di classi portabile è condivisa tra più applicazioni, non è possibile fare riferimento a librerie specifiche della piattaforma ( ad esempio. Community.CsharpSqlite.WP7).
  2. Il sottoinsieme libreria di classi portabile potrebbe non includere classi che altrimenti sarebbero disponibili sia in MonoTouch che in Mono per Android (ad esempio DllImport o System.IO.File).

Nota

Le librerie di classi portabili sono state deprecate nella versione più recente di Visual Studio e sono consigliate le librerie .NET Standard.

In alcuni casi, entrambi gli svantaggi possono essere aggirati usando il modello provider o l'inserimento delle dipendenze per codificare l'implementazione effettiva nei progetti di piattaforma in base a un'interfaccia o a una classe di base definita nella libreria di classi portabile.

Questo diagramma illustra l'architettura di un'applicazione multipiattaforma che usa una libreria di classi portabile per condividere il codice, ma anche l'uso dell'inserimento delle dipendenze per passare le funzionalità dipendenti dalla piattaforma:

Questo diagramma illustra l'architettura di un'applicazione multipiattaforma che usa una libreria di classi portabile per condividere il codice, ma anche l'uso dell'inserimento delle dipendenze per passare le funzionalità dipendenti dalla piattaforma

Visual Studio per Mac procedura dettagliata

Questa sezione illustra come creare e usare una libreria di classi portabile usando Visual Studio per Mac. Per un'implementazione completa, vedere la sezione Esempio di libreria di classi portabile.

Creazione di una libreria di classi portabile

L'aggiunta di una libreria di classi portabile alla soluzione è molto simile all'aggiunta di un normale progetto libreria.

  1. Nella finestra di dialogo Nuovo progetto selezionare l'opzione Libreria portabile multipiattaforma>:>

    Creare un nuovo progetto PCL

  2. Quando viene creata una libreria di classi portabile in Visual Studio per Mac viene configurata automaticamente con un profilo che funziona per Xamarin.iOS e Xamarin.Android. Il progetto PCL verrà visualizzato come illustrato in questo screenshot:

    Progetto PCL nel riquadro della soluzione

La libreria di classi portabile è ora pronta per l'aggiunta del codice. Può anche essere fatto riferimento ad altri progetti (progetti di applicazione, progetti di libreria e anche altri progetti PCL).

Modifica delle impostazioni pcl

Per visualizzare e modificare le impostazioni pcl per questo progetto, fare clic con il pulsante destro del mouse sul progetto e scegliere Opzioni > Compila > generale per visualizzare la schermata mostrata qui:

Opzioni progetto PCL per impostare il profilo

Fare clic su Cambia per modificare il profilo di destinazione per questa libreria di classi portabile.

Se il profilo viene modificato dopo che il codice è già stato aggiunto al PCL, è possibile che la libreria non venga più compilata se il codice fa riferimento a funzionalità che non fanno parte del profilo appena selezionato.

Uso di una libreria di classi portabile

Quando il codice viene scritto in una libreria PCL, l'editor Visual Studio per Mac riconoscerà le limitazioni del profilo selezionato e regola le opzioni di completamento automatico di conseguenza. Ad esempio, questo screenshot mostra le opzioni di completamento automatico per System.IO usando il profilo predefinito (Profile136) usato in Visual Studio per Mac. Si noti che la barra di scorrimento indica circa la metà delle classi disponibili (in realtà sono disponibili solo 14 classi).

Elenco intellisense di 14 classi nella classe System.IO di un PCL

Confrontare questo aspetto con il completamento automatico di System.IO in un progetto Xamarin.iOS o Xamarin.Android. Sono disponibili 40 classi, incluse le classi comunemente usate, File ad esempio e Directory che non si trovano in alcun profilo PCL.

Elenco intellisense di 40 classi nello spazio dei nomi di .NET Framework System.IO

Ciò riflette il compromesso sottostante dell'uso della libreria di classi portabile: la possibilità di condividere il codice facilmente tra molte piattaforme significa che alcune API non sono disponibili perché non hanno implementazioni confrontabili in tutte le piattaforme possibili.

Uso della libreria di classi portabile

Dopo aver creato un progetto PCL, è possibile aggiungere un riferimento a esso da qualsiasi progetto di applicazione o libreria compatibile nello stesso modo in cui si aggiungono normalmente riferimenti. In Visual Studio per Mac fare clic con il pulsante destro del mouse sul nodo Riferimenti e scegliere Modifica riferimenti, quindi passare alla scheda Progetti come illustrato di seguito:

Aggiungere un riferimento a una libreria di classi portabile tramite l'opzione Modifica riferimenti

Lo screenshot seguente mostra il riquadro della soluzione per l'app di esempio TaskyPortable, che mostra la libreria PCL nella parte inferiore e un riferimento alla libreria PCL nel progetto Xamarin.iOS.

Soluzione di esempio TaskyPortable che mostra il progetto PCL

L'output di una libreria di classi portabile (ad esempio, la DLL dell'assembly risultante) può essere aggiunto anche come riferimento alla maggior parte dei progetti. Questo rende pcl un modo ideale per spedire componenti e librerie multipiattaforma.

Esempio di libreria di classi portabile

L'applicazione di esempio TaskyPortable illustra come usare una libreria di classi portabile con Xamarin. Ecco alcuni screenshot delle app risultanti in esecuzione in iOS e Android:

Ecco alcuni screenshot delle app risultanti in esecuzione in iOS, Android e Windows Telefono

Condivide una serie di classi di dati e logica puramente portabili e illustra anche come incorporare requisiti specifici della piattaforma usando l'inserimento delle dipendenze per l'implementazione del database SQLite.

La struttura della soluzione è illustrata di seguito (rispettivamente in Visual Studio per Mac e Visual Studio):

La struttura della soluzione è illustrata qui rispettivamente in Visual Studio per Mac e Visual Studio

Poiché il codice SQLite-NET include parti specifiche della piattaforma (per lavorare con le implementazioni SQLite in ogni sistema operativo diverso) a scopo dimostrativo è stato eseguito il refactoring in una classe astratta che può essere compilata in una libreria di classi portabile e il codice effettivo implementato come sottoclassi nei progetti iOS e Android.

TaskyPortableLibrary

La libreria di classi portabile è limitata nelle funzionalità .NET che può supportare. Poiché viene compilato per l'esecuzione su più piattaforme, non può usare [DllImport] le funzionalità usate in SQLite-NET. SQLite-NET viene invece implementato come classe astratta e quindi viene fatto riferimento al resto del codice condiviso. Di seguito è riportato un estratto dell'API astratta:

public abstract class SQLiteConnection : IDisposable {

    public string DatabasePath { get; private set; }
    public bool TimeExecution { get; set; }
    public bool Trace { get; set; }
    public SQLiteConnection(string databasePath) {
         DatabasePath = databasePath;
    }
    public abstract int CreateTable<T>();
    public abstract SQLiteCommand CreateCommand(string cmdText, params object[] ps);
    public abstract int Execute(string query, params object[] args);
    public abstract List<T> Query<T>(string query, params object[] args) where T : new();
    public abstract TableQuery<T> Table<T>() where T : new();
    public abstract T Get<T>(object pk) where T : new();
    public bool IsInTransaction { get; protected set; }
    public abstract void BeginTransaction();
    public abstract void Rollback();
    public abstract void Commit();
    public abstract void RunInTransaction(Action action);
    public abstract int Insert(object obj);
    public abstract int Update(object obj);
    public abstract int Delete<T>(T obj);

    public void Dispose()
    {
        Close();
    }
    public abstract void Close();

}

Il resto del codice condiviso usa la classe astratta per "archiviare" e "recuperare" oggetti dal database. In qualsiasi applicazione che usa questa classe astratta è necessario passare un'implementazione completa che fornisce la funzionalità effettiva del database.

TaskyAndroid e TaskyiOS

I progetti di applicazione iOS e Android contengono l'interfaccia utente e altro codice specifico della piattaforma usato per collegare il codice condiviso nella libreria di classi portabile.

Questi progetti contengono anche un'implementazione dell'API di database astratta che funziona su tale piattaforma. In iOS e Android il motore di database Sqlite è integrato nel sistema operativo, quindi l'implementazione può essere usata [DllImport] come illustrato per fornire l'implementazione concreta della connettività del database. Di seguito è riportato un estratto del codice di implementazione specifico della piattaforma:

[DllImport("sqlite3", EntryPoint = "sqlite3_open")]
public static extern Result Open(string filename, out IntPtr db);

[DllImport("sqlite3", EntryPoint = "sqlite3_close")]
public static extern Result Close(IntPtr db);

L'implementazione completa può essere visualizzata nel codice di esempio.

Riepilogo

Questo articolo ha brevemente illustrato i vantaggi e le insidie delle librerie di classi portabili, ha illustrato come creare e utilizzare ICL dall'interno di Visual Studio per Mac e Visual Studio e infine ha introdotto un'applicazione di esempio completa, TaskyPortable, che mostra un PCL in azione.