Utilisation du mot-clé extern alias
Aujourd’hui, je vais vous parler d’une petite fonctionnalité de Visual Studio (à partir de VS2005) que j’ai découverte cette semaine après 7 ans de .Net...comme quoi!
La problématique est la suivante :
J’ai un projet WPF qui charge une assembly Helper qui contient des classes et des méthodes statiques pour répondre à différents besoins. Cette assembly contient également certaines constantes qui seront partagées avec d’autres applications utilisant la même base de données. Jusque-là, rien d’extraordinaire. Vient ensuite, la back-end, un serveur Dynamics CRM sur lequel, nous positionnons différents plugins. Ces plugins peut être enregistrés et chargés automatiquement par les Web services du serveur applicatif. Seule contrainte, chaque plugin doit être dans une seule et unique assembly, impossible de charger une seconde assembly car celle-ci ne serait pas “enregistrable” sur le serveur.
Question : comment dupliquer nos classes “utilitaires” et nos constantes au sein des plugins et les maintenir le plus facilement possible?
Réponse : le shared code. Il s’agit d’une technique de chargement dynamique du code source, plus exactement, à la compilation, le fichier source est copié d’une source unique dans chaque projet et ainsi, en maintenant une seule version du fichier, celui-ci est répliqué au sein des différentes applications/plugins.
Pour cela, rien de bien compliqué, il suffit d’ajouter un élément existant à un projet mais au lieu de cliquer sur Ajouter, il faut cliquer sur Ajouter en tant que lien.
L’histoire aurait pu s’arrêter là mais les problèmes ne firent que commencer. Le problème de dupliquer le code de cette façon c’est que vous pouvez arriver dans un cas de collision d’espace de nom. Pour cela, rien de bien compliqué, un projet supplémentaire (par exemple, pour les tests unitaires) qui ajoute une référence vers deux projets de plugin dans lesquels a été copié le code et vous vous retrouvez avec l’erreur : Ambigous reference mais dans un cas où même Visual Studio ne peut résoudre l’objet puisque même en rajoutant le namespace, le conflit est toujours là. A la compilation, vous obtenez même l’erreur : The type 'Crm.Helper.Utility' exists in both 'c:\Users\lomorand\Documents\Visual Studio 2010\Projects\CrmConsole\CRM.Plugin1\bin\Debug\CRM.Plugin1.dll' and 'c:\Users\lomorand\Documents\Visual Studio 2010\Projects\CrmConsole\CRM.Plugin2\bin\Debug\CRM.Plugin2.dll'
Me voilà bien bloqué. Mais avant même que je puisse commencer mes recherches pour trouver une solution, c’est mon nouveau collègue Jonathan qui vint vers moi avec une potentielle solution : l’utilisation du mot-clé extern alias. Celui-ci permet de compléter un espace de nom par un alias, qui lui même représente la liaison (=référence) vers une assembly particulière.
La mise en place est toute simple
Etape 1 : créer un alias
Sur la référence vers votre projet (ici mon plugin), définissez une valeur sur la propriété Aliases (la valeur par défaut est “global”). L’alias doit être différent pour chaque référence vers les projets en conflit.
Etape 2 : utiliser l’alias
Dans votre code, là où se trouve le conflit, déclarez l’alias puis utilisez-le pour préfixer votre espace de nom
extern alias MonAlias;
using MonAlias::Crm.Helper;
Et c’est tout. La référence à l’objet n’est plus ambigûe et la compilation “retombe en marche”.
Pour un exemple plus parlant, je joins une solution représente ce cas pratique :