Bibliothèques de classes portables (PCL)

Conseil

Les bibliothèques de classes portables (PCL) sont considérées comme dépréciées dans les dernières versions de Visual Studio. Bien que vous puissiez toujours ouvrir, modifier et compiler des LCP, pour les nouveaux projets, il est recommandé d’utiliser des bibliothèques .NET Standard pour accéder à une surface d’API plus grande.

Un composant clé de la création d’applications multiplateformes est la possibilité de partager du code entre différents projets spécifiques à la plateforme. Toutefois, cela est compliqué par le fait que différentes plateformes utilisent souvent un sous-ensemble différent de la bibliothèque de classes de base (BCL) .NET et sont donc réellement créées sur un profil de bibliothèque .NET Core différent. Cela signifie que chaque plateforme peut utiliser uniquement des bibliothèques de classes qui sont ciblées sur le même profil, de sorte qu’elles semblent nécessiter des projets de bibliothèque de classes distincts pour chaque plateforme.

Il existe trois approches principales du partage de code qui résolvent ce problème : les projets .NET Standard, les projets de ressources partagées et les projets de bibliothèque de classes portables (PCL).

  • Les projets .NET Standard sont l’approche préférée pour le partage de code .NET. En savoir plus sur les projets .NET Standard et Xamarin.
  • Les projets de ressources partagées utilisent un ensemble unique de fichiers et offrent un moyen simple et rapide de partager du code au sein d’une solution et utilisent généralement des directives de compilation conditionnelle pour spécifier les chemins de code pour les différentes plateformes qui l’utiliseront (pour plus d’informations, consultez l’article Projets partagés).
  • Les projets PCL ciblent des profils spécifiques qui prennent en charge un ensemble connu de classes/fonctionnalités BCL. Toutefois, le côté inférieur de PCL est qu’ils nécessitent souvent un effort architectural supplémentaire pour séparer le code spécifique du profil dans leurs propres bibliothèques.

Cette page explique comment créer un projet PCL qui cible un profil spécifique, qui peut ensuite être référencé par plusieurs projets spécifiques à la plateforme.

Qu’est-ce qu’une bibliothèque de classes portable ?

Lorsque vous créez un projet d’application ou un projet de bibliothèque, la DLL résultante est limitée à travailler sur la plateforme spécifique pour laquelle elle est créée. Cela vous empêche d’écrire un assembly pour une application Windows, puis de le réutiliser sur Xamarin.iOS et Xamarin.Android.

Toutefois, lorsque vous créez une bibliothèque de classes portable, vous pouvez choisir une combinaison de plateformes sur lesquelles vous souhaitez que votre code s’exécute. Les choix de compatibilité que vous effectuez lors de la création d’une bibliothèque de classes portable sont traduits en identificateur « Profil », qui décrit les plateformes prises en charge par la bibliothèque.

Le tableau ci-dessous présente certaines des fonctionnalités qui varient selon la plateforme .NET. Pour écrire un assembly PCL dont l’exécution est garantie sur des appareils/plateformes spécifiques, vous devez simplement choisir la prise en charge requise lors de la création du projet.

Fonctionnalité .NET Framework Applications UWP Silverlight Windows Phone Xamarin
Core O O O O O
LINQ O O O O O
IQueryable O O O 7.5 + O
Sérialisation O O O O O
Annotations de données 4.0.3 + O O O

La colonne Xamarin reflète le fait que Xamarin.iOS et Xamarin.Android prennent en charge tous les profils fournis avec Visual Studio, et la disponibilité des fonctionnalités dans toutes les bibliothèques que vous créez sera limitée uniquement par les autres plateformes que vous choisissez de prendre en charge.

Cela inclut les profils qui sont des combinaisons de :

  • .NET 4 ou .NET 4.5
  • Silverlight 5
  • Windows Phone 8
  • Applications UWP

Vous pouvez en savoir plus sur les fonctionnalités des différents profils sur le site web de Microsoft et consulter le résumé du profil PCL d’un autre membre de la communauté qui comprend des informations de framework prises en charge et d’autres notes.

Avantages

  1. Partage de code centralisé : écrivez et testez du code dans un seul projet qui peut être consommé par d’autres bibliothèques ou applications.
  2. Les opérations de refactorisation affectent tout le code chargé dans la solution (la bibliothèque de classes portable et les projets spécifiques à la plateforme).
  3. Le projet PCL peut être facilement référencé par d’autres projets dans une solution, ou l’assembly de sortie peut être partagé pour que d’autres personnes puissent faire référence dans leurs solutions.

Inconvénients

  1. Étant donné que la même bibliothèque de classes portable est partagée entre plusieurs applications, les bibliothèques spécifiques à la plateforme ne peuvent pas être référencées (par exemple. Community.CsharpSqlite.WP7).
  2. Le sous-ensemble bibliothèque de classes portable peut ne pas inclure des classes qui seraient autrement disponibles dans MonoTouch et Mono pour Android (telles que DllImport ou System.IO.File).

Notes

Les bibliothèques de classes portables ont été dépréciées dans la dernière version de Visual Studio, et les bibliothèques .NET Standard sont recommandées à la place.

Dans une certaine mesure, les deux inconvénients peuvent être contournés à l’aide du modèle fournisseur ou de l’injection de dépendances pour coder l’implémentation réelle dans les projets de plateforme sur une interface ou une classe de base définie dans la bibliothèque de classes portable.

Ce diagramme montre l’architecture d’une application multiplateforme utilisant une bibliothèque de classes portable pour partager du code, mais également l’injection de dépendances pour transmettre des fonctionnalités dépendantes de la plateforme :

Ce diagramme montre l’architecture d’une application multiplateforme utilisant une bibliothèque de classes portable pour partager du code, mais également l’injection de dépendances pour transmettre des fonctionnalités dépendantes de la plateforme

procédure pas à pas Visual Studio pour Mac

Cette section explique comment créer et utiliser une bibliothèque de classes portable à l’aide de Visual Studio pour Mac. Pour une implémentation complète, reportez-vous à la section Exemple PCL.

Création d’une LCP

L’ajout d’une bibliothèque de classes portable à votre solution est très similaire à l’ajout d’un projet bibliothèque standard.

  1. Dans la boîte de dialogue Nouveau projet, sélectionnez l’option Bibliothèque portable multiplateforme >> :

    Créer un projet PCL

  2. Lorsqu’une LCP est créée dans Visual Studio pour Mac elle est automatiquement configurée avec un profil qui fonctionne pour Xamarin.iOS et Xamarin.Android. Le projet PCL s’affiche comme illustré dans cette capture d’écran :

    Projet PCL dans le volet solution

La LCP est maintenant prête pour l’ajout de code. Il peut également être référencé par d’autres projets (projets d’application, projets de bibliothèque et même d’autres projets PCL).

Modification des paramètres PCL

Pour afficher et modifier les paramètres PCL pour ce projet, cliquez avec le bouton droit sur le projet et choisissez Options > Build > General pour afficher l’écran affiché ici :

Options de projet PCL pour définir le profil

Cliquez sur Modifier... pour modifier le profil cible de cette bibliothèque de classes portable.

Si le profil est modifié une fois que le code a déjà été ajouté à la LCP, il est possible que la bibliothèque ne soit plus compilée si le code référence des fonctionnalités qui ne font pas partie du profil nouvellement sélectionné.

Utilisation d’une LCP

Lorsque le code est écrit dans une bibliothèque PCL, l’éditeur de Visual Studio pour Mac reconnaît les limitations du profil sélectionné et ajuste les options de saisie semi-automatique en conséquence. Par exemple, cette capture d’écran montre les options de saisie semi-automatique pour System.IO utilisant le profil par défaut (Profil136) utilisé dans Visual Studio pour Mac . Notez que la barre de défilement qui indique qu’environ la moitié des classes disponibles sont affichées (en fait, il n’y a que 14 classes disponibles).

Liste Intellisense de 14 classes dans la classe System.IO d’une LCP

Comparez cela avec le System.IO la saisie semi-automatique dans un projet Xamarin.iOS ou Xamarin.Android : il existe 40 classes disponibles, y compris les classes couramment utilisées telles que File et Directory qui ne se trouvent dans aucun profil PCL.

Liste Intellisense de 40 classes dans l’espace de noms .NET Framework System.IO

Cela reflète le compromis sous-jacent de l’utilisation de la LCP : la possibilité de partager du code en toute transparence sur de nombreuses plateformes signifie que certaines API ne sont pas disponibles, car elles n’ont pas d’implémentations comparables sur toutes les plateformes possibles.

Utilisation de la LCP

Une fois qu’un projet PCL a été créé, vous pouvez lui ajouter une référence à partir de n’importe quel projet d’application ou de bibliothèque compatible de la même façon que vous ajoutez normalement des références. Dans Visual Studio pour Mac, cliquez avec le bouton droit sur le nœud Références, choisissez Modifier les références... puis basculez vers l’onglet Projets comme indiqué :

Ajouter une référence à une LCP via l’option Modifier les références

La capture d’écran suivante montre le volet Solution de l’exemple d’application TaskyPortable, montrant la bibliothèque PCL en bas et une référence à cette bibliothèque PCL dans le projet Xamarin.iOS.

Exemple de solution TaskyPortable montrant le projet PCL

La sortie d’une LCP (c’est-à-dire la DLL d’assembly résultante) peut également être ajoutée en tant que référence à la plupart des projets. Cela fait de PCL un moyen idéal d’expédier des composants et des bibliothèques multiplateformes.

Exemple PCL

L’exemple d’application TaskyPortable montre comment une bibliothèque de classes portable peut être utilisée avec Xamarin. Voici quelques captures d’écran des applications résultantes s’exécutant sur iOS et Android :

Voici quelques captures d’écran des applications qui s’exécutent sur iOS, Android et Windows Phone

Il partage un certain nombre de données et de classes logiques qui sont du code purement portable, et il montre également comment incorporer des exigences spécifiques à la plateforme à l’aide de l’injection de dépendances pour l’implémentation de la base de données SQLite.

La structure de la solution est illustrée ci-dessous (respectivement dans Visual Studio pour Mac et Visual Studio) :

La structure de la solution est illustrée ici dans Visual Studio pour Mac et Visual Studio, respectivement.

Étant donné que le code SQLite-NET comporte des éléments spécifiques à la plateforme (pour utiliser les implémentations SQLite sur chaque système d’exploitation) à des fins de démonstration, il a été refactorisé en une classe abstraite qui peut être compilée dans une bibliothèque de classes portable et le code réel implémenté en tant que sous-classes dans les projets iOS et Android.

TaskyPortableLibrary

La bibliothèque de classes portable est limitée dans les fonctionnalités .NET qu’elle peut prendre en charge. Étant donné qu’il est compilé pour s’exécuter sur plusieurs plateformes, il ne peut pas utiliser les [DllImport] fonctionnalités utilisées dans SQLite-NET. Au lieu de cela, SQLite-NET est implémenté en tant que classe abstraite, puis référencé par le reste du code partagé. Un extrait de l’API abstraite est illustré ci-dessous :

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();

}

Le reste du code partagé utilise la classe abstraite pour « stocker » et « récupérer » des objets de la base de données. Dans toute application qui utilise cette classe abstraite, nous devons passer une implémentation complète qui fournit la fonctionnalité de base de données réelle.

TaskyAndroid et TaskyiOS

Les projets d’application iOS et Android contiennent l’interface utilisateur et d’autres codes spécifiques à la plateforme utilisés pour connecter le code partagé dans la LCP.

Ces projets contiennent également une implémentation de l’API de base de données abstraite qui fonctionne sur cette plateforme. Sur iOS et Android, le moteur de base de données Sqlite étant intégré au système d’exploitation, l’implémentation peut utiliser [DllImport] comme indiqué pour fournir l’implémentation concrète de la connectivité de base de données. Un extrait du code d’implémentation spécifique à la plateforme s’affiche ici :

[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’implémentation complète est visible dans l’exemple de code.

Résumé

Cet article a brièvement abordé les avantages et les pièges des bibliothèques de classes portables, a montré comment créer et consommer des LCP à partir de Visual Studio pour Mac et Visual Studio; et enfin présenté un exemple d’application complet – TaskyPortable – qui montre une LCP en action.