Dot.Blog

C#, XAML, Xamarin, UWP/Android/iOS

Contourner les limites des PCL par la technique d’injection de code natif (cross-plateforme)

[new:30/09/2013]Les Portable Class Libraries de Visual Studio sont une aide appréciable pour l’écriture des projets cross-plateforme. Mais certains espaces de noms ne sont pas supportés… Comment contourner ce problème ?

Des espaces de noms non intégrés aux PCL

Il existe des espaces de noms qui ne font pas partie du noyau commun exposé par les PCL. J’ai eu dernièrement le problème pour System.Security.Cryptography.

Au sein d’un projet cross-plateforme Android/WPF j’étais en train d’écrire une fonction de cryptage / décryptage dans le noyau PCL quand je me suis aperçu que l’espace de noms indiqué ci-dessus n’était hélas pas intégré au jeu réduit du profil .NET de la PCL… Fâcheux…

Heureusement, ce joli code je le tenais d’un autre projet et j’avais seulement copier/coller l’unité de code. Donc pas vraiment de perte de temps. C’est maintenant que le temps allait défiler bêtement, en essayant de résoudre ce problème simple : Pas de cryptographie dans le .NET de la PCL…

Phase 1 : Xamarin à la rescousse

Le noyau CPL ne gère pas l’espace de nom dont j’ai besoin, mais est-ce que Xamarin le gère ? Car si la réponse est non, il va vraiment falloir partir sur une réécriture…

Après vérification Xamarin pour Android possède bien l’espace de nom de cryptographie et expose tout ce qu’il faut, parfaitement compatible avec le code .NET que je venais de récupérer d’un autre projet (Silverlight, c’est pour dire si tout cela est fantastiquement compatible au final !).

Ce fut un premier soulagement, car si la partie Android pouvait grâce à Xamarin faire tourner le code déjà écrit, fortes étaient les chances que le .NET ultra musclé de WPF pourrait le faire sans souci.

Phase 2 : Comment appeler du code Xamarin ou .NET dans le noyau .NET CPL ?

Je me suis immédiatement souvenu de la Vidéo 12 : Injection de code natif (WinRT/Android) que je vous ai présentée le 16 aout dernier…

Dans cette vidéo je démontre comment utiliser dans le noyau CPL du code véritablement natif et spécifique à chaque plateforme de façon simple et transparente.

Certes ici je n’avais pas de code “natif”, juste du bon .NET bien standard !

Oui mais hélas utilisant un espace de noms non intégré au mécanisme des PCL !

L’idée m’est donc venue de traiter ce code comme du code natif…

Phase 3 : implémentation

Je vais passer les détails puisque la technique est entièrement décrite avec moult détails dans la vidéo sus-indiquée, il suffit de suivre le lien et de regarder… (et d’écouter aussi, mais en général ça coule de source quand on regarde un tutor…).

Je vais donc uniquement résumé le “plan” :

1) Déclarer une interface dans le noyau, imaginons “ICryptoService”’ déclarant deux méthodes, l’une pour crypter, l’autre pour décrypter.

2) Dans le projet Android (ça aurait pu être le projet WPF, j’ai pris le 1er dans la liste de ma solution) j’ai créé une classe NativeCryptoService : ICryptoSerrvice qui implémente les deux méthodes. En réalité ici un simple copier coller du code d’un ancien projet Silverlight donc. Avec l’aide de Resharper tous les “using” s’ajoutent facilement.

3) Dans le Setup.cs (mécanisme MvvmCross) j’ai ajouté comme montré dans la vidéo un override de InitializeLastChance() méthode dans laquelle j’ai tout simplement ajouté le type de ma classe native dans le conteneur IoC en tant que singleton. A la première utilisation le conteneur créera l’instance et la conservera pour les appels futurs.

4) Dans le projet WPF (qui aurait donc pu être le projet Android, l’ordre n’a pas de sens ici) j’ai ajouté un répertoire pour le code natif et j’ai ajouté un “existing item”. Cet item existant c’est le fichier contenant l’implémentation se trouvant dans le projet Android (étape 2). Mais en ajoutant le fichier j’ai demandé à VS de simplement créer un lien : de fait je n’ai aucun code répétitif, l’unité de code n’existe qu’en un seul exemplaire.

5) Dans le setup.cs du projet WPF j’ai ajouté le singleton comme à l’étape 3 pour le projet Android.

Et c’est tout…

Pour utiliser ce code “natif” dans la PCL je n’ai plus qu’à faire de l’injection de dépendance via les constructeurs et je récupère le singleton, ou bien si ce n’est pas dans un ViewModel ou un Service, je peux appeler directement Mvx.Resolve() pour récupérer le singleton.

Mon noyau est dès lors capable d’utiliser les services de cryptographie pourtant indisponibles dans une PCL… Le code natif n’existe qu’une fois dans un seul projet d’UI, il est juste référencé en lien dans le second.

Conclusion

Dans les 12 vidéos que je vous ai concoctées cet été il y a mille et une astuce présentées. En y ajoutant une pointe de créativité on peut en démultiplier l’intérêt…

Ici j’ai pu utiliser la cryptographie dans le projet noyau alors que cet espace de nom n’existe pas dans le profil .NET de la CPL. Le code est unique, non dupliqué, mais lorsque je compile la solution, le projet noyau est compilé par le compilateur Microsoft de CPL, le code de cryptographie sera compilé par le compilateur Xamarin Android dans le projet Android et le code lié (identique) dans le projet WPF sera compilé par le compilateur .NET de WPF…

C’est un joli tour de passe-passe, très simple à réaliser, et qui montre, une fois de plus, l’intérêt de travailler en cross-plateforme et d’utiliser les bons outils : Visual Studio, Xamarin et MvvmCross et surtout C# !

Stay Tuned !

blog comments powered by Disqus