Bonjour à tous,
J’explique mon “problème”. Dans l’application sur laquelle je travaille, nous avons une fonctionnalité qui permet aux utilisateurs de créer des modules, sous la forme d’assembly (.dll) .Net permettant de faire des exportation et importation de données.
Il y a une interface graphique dans le programme qui permet à l’utilisateur de chercher sur son disque une assembly et de la charger. A ce moment, nous devons regarder dans la dll qui a été chargée pour vérifier plusieurs choses :
- Est-ce que c’est bien une assembly .Net
- Est-ce qu’elle contient bien les fonctionnalités qu’on attends d’elle
- Quel est le type d’exportation qu’elle est capable de faire
- Quel sont les cibles possibles pour ces importations
Les deux premiers points sont faciles à gérer, le premier il suffit de récupérer l’exception qui est levée quand on ouvre l’assembly si elle n’est pas lisible. Pour la seconde j’ai simplement fait une classe de base, abstraite (ExportBase et ImportBase) qui contient la méthode publique DoExport et DoImport qui appelle d’autres méthodes virtual, privées celles-ci qui vont charger les données et les exporter vers la cible (ou l’inverse).
Pour le troisième cas, en gros, j’ai un certains nombre de type d’éléments qui peuvent être importer et exporter, disons des clients, des utilisateurs et des fournisseurs. J’ai une classe pour chacun de ces types.
Lorsque je charge une assembly, elle est susceptible de contenir plusieurs classes du type ExportBase et l’utilisateur doit donc choisir quel type il veut exporter. Je dois donc regarder l’ensemble des classes contenues dans l’assembly et enabler ou disabler des fonctionnalités en fonction des classes présentes dans l’assembly.
Pour faire ça, j’ai créé une interface pour chacun des types. Par exemple, IClientExport. Cette interface hérite de l’interface IExport qui est implémentée par ExportBase. De cette façon, pour vérifier qu’une classe dans l’assembly est capable d’exporter des clients, j’ai juste à vérifier qu’elle implémente bien IClientExport.
Jusque là ça me semble relativement logique, et ça fonctionne bien.
Là où j’ai un doute c’est la manière dont j’ai fait le quatrième cas. Chaque export peut avoir une ou plusieurs cibles, par exemple ma classe qui implémente IClientExport peut exporter mes clients soit vers le disque dur via un fichier, soit vers un web service. Le truc c’est que chaque module peut implémenter une ou plusieurs cibles. Par exemple un module peut n’exporter que vers un web service, un autre que vers des fichiers et un autre encore vers tout. L’utilisateur doit donc pouvoir choisir vers quelle cible il veut effectuer l’exportation, mais j’aimerais restreindre les cibles possibles à celles qui sont disponibles pour le module sélectionné.
La manière dont j’ai implémenté ça est la suivante, dans ma classe ExportBase, j’ai une propriété statique en lecture seule qui me renvoie les cible possibles (une tableau de type énumératif). Dans chacune des classes qui hérites de ExportBase (celles qui implémentent les modules) je redéfinis la propriété statique en utilisant le mot-clef new. C’est un peu cette utilisation du mot-clef new qui me chiffone, mais je ne vois pas bien comment faire ça autrement, c’est un work-around pour la non-existence de l’héritage des attributs statiques de C#… mais je suis certain qu’il y a un autre moyen de faire ça… quelqu’un aurait une idée?