mars
2010
MEF (Managed Extensibility Framework) est un framework développé par Microsoft qui permet de créer des applications extensible facilement.
Il fonctionne comme un système de plugin et est capable de composer une application en chargeant des extensions à des endroits prédéfinis. Cela permet d’étendre un logiciel sans avoir besoin de connaitre à l’avance le fonctionnement du plug-in, tant que le celui-ci respecte un contrat ; grâce à la fonctionnalité de découverte de MEF.
MEF fonctionne grâce à des annotations et des attributs.
L’attribut Export permet d’informer MEF qu’il se trouve en présence d’un plugin qui respecte un contrat particulier.
L’attribut Import permet d’indiquer à MEF qu’il doit se débrouiller pour nous fournir quelque chose qui respecte un contrat précis.
MEF est actuellement en développement (Preview 9 à l’heure où j’écris ces lignes), son API est susceptible d’évoluer.
Pour illustrer cette introduction, nous allons construire une petite application de démo.
Pour utiliser MEF, il suffit de récupérer le code à cet emplacement http://www.codeplex.com/MEF et de copier la DLL System.ComponentModel.Composition.dll.
Je créé une application Console que je nomme testMef puis 2 projet de type Class Library que je nomme HelloWorldService.Contract et HelloWorldService.
HelloWorldService.Contract contiendra l’interface suivante :
1: public interface IHelloWorldService
2: {
3: string Hello(string who);
4: }
HelloWorldService contiendra le classe suivante :
1: public class HelloWorldService : IHelloWorldService
2: {
3: public string Hello(string who)
4: {
5: return "Hello " + who;
6: }
7: }
Dans mon application console, je crée une classe ClassicRunner qui va instancier mon service et appeler sa méthode Hello.
1: public class ClassicRunner
2: {
3: public void Run()
4: {
5: IHelloWorldService helloWorldService = new HelloWorldService.HelloWorldService();
6: Console.WriteLine(helloWorldService.Hello("Nico"));
7: }
8: }
Nous introduisons ici une dépendance forte au projet HelloWorldService.
Je peux bien sur utiliser cette classe dans le point d’entrée de mon application console avec :
1: public class Program
2: {
3: public static void Main(string[] args)
4: {
5: ClassicRunner classicRunner = new ClassicRunner();
6: classicRunner.Run();
7: }
8: }
Maintenant, faisons la même chose à la mode MEF.
La première chose à faire est de dire à MEF que la classe HelloWorldService est un plugin et se rend disponible pour un contrat particulier. Comme expliqué en introduction, cela se fait avec l’attribut Export :
1: [Export(typeof(IHelloWorldService))]
2: public class HelloWorldService : IHelloWorldService
3: {
4: public string Hello(string who)
5: {
6: return "Hello " + who;
7: }
8: }
Créons maintenant une classe MefRunner qui va s’occuper d’appeler un plugin respectant le contrat IHelloWorldService.
1: public class MefRunner
2: {
3: [Import]
4: public IHelloWorldService HelloWorldService { get; set; }
5:
6: public void Run()
7: {
8: Compose();
9: Console.WriteLine(HelloWorldService.Hello("Nico"));
10: }
11:
12: private void Compose()
13: {
14: string currentDirectory = new FileInfo(Assembly.GetCallingAssembly().Location).Directory.ToString();
15: AggregateCatalog catalog = new AggregateCatalog(new AssemblyCatalog(Assembly.GetExecutingAssembly()), new DirectoryCatalog(currentDirectory));
16: var container = new CompositionContainer(catalog);
17: container.ComposeParts(this);
18: }
19: }
On voit ici qu’on déclare une propriété de type IHelloWorldService, décorée de l’attribut Import. Cela nous permet de demander à MEF de se débrouiller pour nous fournir quelque chose qui respecte le contrat de la propriété.
Il nous faut maintenant demander à MEF de s’initialiser et d’utiliser sa capacité de découverte de plug-in pour aller fouiller à un emplacement s’il y a un plugin qui pourrait nous être utile.
Pour ce faire, on va utiliser l’objet AggregateCatalog pour lui indiquer de chercher dans l’assembly courante et dans le répertoire de l’exécutable (ce qu’on trouve dans la méthode Compose).
enfin, le CompositionContainer permet d’initialiser MEF.
On voit dans le code du MefRunner qu’aucune référence n’est faite au projet HelloWorldService.
Cependant, la DLL doit bien sur être présente dans le répertoire que nous avons indiqué à MEF (ici, le répertoire de l’exécutable).
Il ne restera qu’à appeler le MefRunner :
1: public class Program
2: {
3: public static void Main(string[] args)
4: {
5: MefRunner mefRunner = new MefRunner();
6: mefRunner.Run();
7: }
8: }
Notez que MEF n’est pas un IOC, comme Unity. Mais il se sert des techniques d’inversions de contrôles pour son système de plugin.
On peut considérer qu’un IOC est approprié quand il s’agit de charger des dépendances connues à l’avance, alors que MEF est plutôt adapté à la découverte de dépendances inconnues.
Vous pouvez télécharger l’application exemple à cet emplacement.
Commentaires récents
- [Tests] Arrange Act Assert, une traduction ? dans
- [UnitTest][C#] Tester une méthode privée dans
- Récupérer une valeur d’un contrôle depuis une autre Form / inclusions croisées et déclaration anticipée dans
- Tutoriel : Utiliser la ListBox et l’Isolated Storage dans vos applications Windows Phone 7 avec Silverlight dans
- Tutoriel : Utiliser la ListBox et l’Isolated Storage dans vos applications Windows Phone 7 avec Silverlight dans
Archives
- janvier 2013
- avril 2012
- janvier 2012
- juin 2011
- janvier 2011
- décembre 2010
- novembre 2010
- septembre 2010
- juin 2010
- mars 2010
- février 2010
- janvier 2010
- décembre 2009
- novembre 2009
- octobre 2009
- septembre 2009
- août 2009
- juillet 2009
- mai 2009
- avril 2009
- mars 2009
- janvier 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- août 2008
- juillet 2008
- juin 2008
- mai 2008
- avril 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- octobre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007