‘ExportFactory’ personnalisé

Une application de bureau utilisant MEF importe de nombreux «prestataires de services». Chaque partie (ServiceProvider) est une classe dans une DLL distincte. Toutes les DLL se trouvent dans le dossier “Plugin” utilisé par l’application de bureau.

Comme j’avais besoin de nouvelles instances de mes pièces, ExportFactory était le meilleur choix. Le problème est que mes pièces ont des constructeurs. J’ai besoin de passer quelques parameters dans le constructeur de la pièce qui n’est pas prise en charge par ExportFactory (MEF2, Preview2).

J’ai besoin de quelque chose comme ça:

 // Each part has its own dependency Dependency dependency = LoadDependency(myPart.Metedata["Name"]); // Injecting dependency into part's constructor myPart.CreateExport(dependency); 

Je ne veux rien importer de mon côté des pièces.

Un exemple de projet (avec constructeur sans paramètre) peut être trouvé ici .

Lorsque MEF voit une importation du type ExportFactory , il la traite de manière particulière. Au lieu de rechercher littéralement une ExportFactory , elle recherche plutôt une exportation IFoo et génère par magie une fabrique pour ce type.

Votre erreur est que vous vous attendez à ce que cette magie fonctionne également automatiquement pour votre propre alternative à ExportFactory que vous avez appelée SrviceProviderFactory . Ce n’est pas vrai. Lorsque vous importez SrviceProviderFactory quelque part, MEF recherche littéralement une exportation de ce type.

La solution simple est de lui donner cette exportation. Exportez manuellement une usine pour chaque implémentation IServiceProvider. Par exemple, si vous avez un FooServiceProvider :

 public class FooServiceProvider : IServiceProvider { public FooServiceProvider(Dependency dependency) { ... } } 

Ensuite, vous devez également disposer d’une FooServiceProviderFactory:

 [Export(typeof(IServiceProviderFactory))] [ExportMetaData("foo", "bar")] public class FooServiceProviderFactory : IServiceProviderFactory { public IServiceProvider CreateServiceProvider(Dependency d) { return new FooServiceProvider(d); } } 

Et puis votre importateur peut sélectionner la bonne usine en fonction des métadonnées:

 public class FactoryUser { [ImportMany] public Lazy>[] Factories { get; set; } public void DoSomething() { var factory = Factories.First(x => x.Metadata["foo"] == "bar").Value; var serviceProvider = factory.CreateServiceProvider(someDependency); ... } } 

Ce qui est ennuyeux ici, c’est que pour chaque implémentation de fournisseur de services, vous devez également créer et exporter une implémentation d’usine. Vous pouvez enregistrer le travail en créant une classe de base fabrique commune (telle que votre SrviceProviderFactory ), mais vous devez toujours dériver des classes spécifiques car vous ne pouvez pas utiliser de parameters de type générique dans les exportations MEF. Mise à jour : Je pense que .NET 4.5 prend désormais en charge l’exportation de types génériques ouverts.

C’est pourquoi j’ai déjà suggéré d’exporter Func place , mais apparemment, cette réponse ne vous a pas plu.

Vous pouvez également essayer de répliquer la magie ExportFactory . C’est possible, mais c’est un cas d’utilisation très avancé de MEF. Si vous souhaitez le faire, je vous suggère de consulter les sources MEF de ExportFactoryProvider pour voir comment créer votre propre implémentation avec prise en charge des parameters.