Portable Class Library : partager efficacement du code entre plateformes

Nathanael Marchand

Lorsque l'on développe pour plusieurs plateformes (.Net, Silverlight, XNA, Windows Phone 7), il se pose souvent la question de comment partager le code ? La Portable Class Library permet de répondre efficacement à cette problématique puisqu'elle permet à un projet d'être multiplateforme. Nous allons voir comment l'utiliser dans un cas de figure où il faut partager du code entre un client Silverlight et le serveur.
Commentez ♪

- Titre : Portable Class Library : partager efficacement du code entre plateformes

- Auteur : Nathanael Marchand

- Parution : 21 juin 2011

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2011 Nathanael Marchand. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.

Sommaire

- I. Pourquoi partager du code ?

- II. Partager du code « avec les moyens du bord »

- III. Principe et utilisation de la Portable Class Library

- IV. Conclusion

I - Pourquoi partager du code ?

La question est assez simple, la réponse l'est tout autant : la factorisation ! Il est très contraignant de devoir maintenir deux codes identiques. Bien souvent, on met à jour l'un en oubliant l'autre, il y a des problèmes de synchronisation, bref une belle source de bugs !
Il y a également une problématique bien connue des personnes utilisant du Silverlight : les proxys de services Web générés pas Visual Studio. Prenons notre solution de test : nous exposons trois services et trois entités différents comme ci-dessous.

Lorsque Visual Studio génère les proxys, on s'aperçoit d'une chose étrange : une même entité côté serveur correspond à plusieurs entités côté client (une par proxy de service) !

Bien sûr, ces entités ne sont pas compatibles entre les namespaces, ce qui peut poser problème dans l'utilisation de celles-ci. Nous allons donc créer une librairie qui contient nos entités côté client dans le chapitre suivant.

II - Partager du code « avec les moyens du bord »

D'une manière naïve, nous pourrions essayer d'ajouter au projet Silverlight une référence vers le projet de nos entités. Cela n'est pas possible, ils ne sont pas destinés à la même plateforme. Il faut donc créer un nouveau projet Silverlight qui contient le même code que la version .Net. Toujours d'une manière naïve, nous pourrions copier-coller le code entre les deux projets : cela s'avère peu efficace et bien souvent source de bugs ! Nous pouvons donc ruser un peu : au lieu de copier le code, dans le nouveau projet, nous allons ajouter les fichiers en tant que lien. Ils ne seront présents que logiquement et non pas physiquement.

Désormais, les fichiers apparaissent avec une petite flèche de raccourci et il est possible de faire une référence sur ce projet depuis l'application Silverlight. Reste à dire lors de la création d'un proxy qu'il faut utiliser ces entités : c'est fait automatiquement par Visual Studio si la référence est correcte.
Cependant, bien que cela soit la meilleure solution qui existait, elle n'était pas parfaite : même s'il ne fallait plus se soucier du contenu des fichiers, il fallait toujours penser à répliquer l'ajout/déplacement des fichiers. Là encore, cela pouvait être source de bug. C'est pour cela que sont arrivés les Portable Library Tools.

III - Principe et utilisation de la Portable Class Library

La Portable Class Library est un nouveau type de projet apporté par les Portable Library Tools (extension Visual Studio disponible ici). Un projet de ce type pourra être référencé à la fois par un projet .Net standard mais également un projet Silverlight, Windows Phone 7 et XNA.
Bien sûr, cela ne va pas sans contraintes : le framework XNA n'est pas aussi complet que .Net, il faut donc faire attention à la partie du framework qui est utilisée. Voici un tableau extrait de MSDN qui résume les possibilités :

Fonctionnalité

Assemblies

.NET

Silverlight

Windows Phone 7

XNA

Core

mscorlib.dll, System.dll, System.Core.dll, System.Xml.dll

Oui

Oui

Oui

Oui

Managed Extensibility Framework (MEF)

System.ComponentModel.Composition.dll

Oui

Oui

Non

Non

Network Class Library (NCL)

System.Net.dll

Oui

Oui

Oui

Non

Serialization

System.Runtime.Serialization.dll

Oui

Oui

Oui

Non

Windows Communication Foundation (WCF)

System.ServiceModel.dll

Oui

Oui

Oui

Non

XML Serialization

System.Xml.Serialization.dll

Oui

Oui

Oui

Non

View Model Support

System.Windows.dll (from Silverlight)

Non

Oui

Oui

Non

Il faut par conséquent déterminer quelles sont les plateformes qui nous intéressent et les configurer dans les options du projet, comme ci-dessous.

Désormais, nous pouvons utiliser ce projet et le référencer à la fois dans notre couche service côté serveur et dans notre application côté Silverlight.

Il est à noter que cet outil nécessite une mise à jour du Framework 4 (déployé lors de l'installation du SP1 de Visual Studio) disponible ici. Il est également nécessaire d'avoir Silverlight au moins en version 4.0.60129.0.

Il est à noter également que l'utilisation de ObservableCollection<T> n'est pas possible lorsque le framework .NET 4 est en cible car cette classe n'est pas dans les mêmes assemblies sur Silverlight et .NET 4

IV - Conclusion

On voit clairement une nouvelle fois la stratégie trois écrans (PC, WP7 et XBOX360) de Microsoft : proposer le même contenu sur tous les appareils possibles. D'une manière assez conviviale, on peut désormais partager nos entités entre le serveur et le client Silverlight/WP7 ou partager les ViewModels entre Silverlight et WP7 lors de l'utilisation du MVVM. Les sources sont disponibles sur ce lien.
Merci à jacques_jean pour sa relecture attentive.