2010-08-03 4 views
2

J'ai une application (juste un test) qui utilise MEF et PRISM.Configurer et exposer un singleton à tous les modules d'une application MEF/PRISM

Il est assez facile de charger des exports conformes aux interfaces spécifiques et de les passer au constructeur des modules en cours de chargement, mais j'essaie de faire quelque chose de différent. Lorsque l'application démarre, elle importe une implémentation de IControllerClient.

L'instance créée doit ensuite être configurée (par le shell par exemple), après quoi chaque module de l'application doit avoir accès à .

Je ne veux pas avoir une propriété publique sur le shell ou une classe d'assistance qui expose cette instance car cela serait probablement considéré comme une mauvaise pratique ... et je ne l'aime pas vraiment.

Mise à jour:reformulant la question ci-dessous

Nous avons un certain nombre d'interfaces définies dans un cadre existant, normalement ceux-ci sont chargées à l'aide dans diverses applications MEF.

j'ai pu les charger dans un module dans une application prisme, par exemple comme ceci:

[ImportingConstructorAttribute()] 
public HelloWorldView(IDataTransportService dataTransportService, 
         IMessageFactory messageFactory, 
         IDataFactory dataFactory, 
         IDataProcessor dataProcessor, 
         IDataCollector dataCollector) 
{ 
     var client = new ControllerClient(dataTransportService, 
              messageFactory, 
              dataProcessor 
              dataCollector); 
} 

Dans ce cas, le module crée une instance valide de la classe ControllerClient.

Mais au lieu de passer ces interfaces au constructeur, je veux avoir un module constructeur comme ceci:

[ImportingConstructorAttribute()] 
public HelloWorldView(IClient client) 
{ 
    this.client = client; 
} 

Le constructeur de la mise en œuvre de iClient (ControllerClient) a le [ImportingConstructorAttribute()] pour Je m'attendais à ce que les dépences soient automatiquement injectées à ... cependant en utilisant ce code, le constructeur n'est jamais atteint. Ce que je veux est d'avoir une instance d'une interface IClient qui est utilisée par TOUS les modules dans l'application

(Je comprends maintenant Shared est la valeur par défaut pour les importations MEF).

Quelle est la meilleure façon de faire cela? Pourquoi est-ce que je ne peux pas avoir un constructeur de module prenant un IClient, et si je voulais exposer une instance d'une classe de cette façon s'il n'a pas la connaissance de mef?

Donc, dans une application mef/prism, où définiriez-vous cette instance qui peut être utilisée par tous les modules? Et est-ce ce qu'on appelle souvent un service (mais je ne pouvais trouver des conseils sur l'exposition des services avec unité/prisme). J'espère que j'ai mieux fait d'expliquer mon problème cette fois ci.

Mise à jour 2: Étant donné que le défaut est partagé pour les importations MEF, je pourrais importer la mise en œuvre de iClient dans chaque module, mais je dois comprendre pourquoi les dépendances ne sont pas injectés

+0

Quel est le problème avec la définition d'une PartCreationPolicy? Il me semble que c'est exactement ce dont vous avez besoin. –

+0

Je suis probablement expliquer mon problème de façon incorrecte .. Je vais essayer de le reformuler, désolé – TimothyP

Répondre

2

Pour MEF, Shared est la valeur par défaut, de sorte que chaque importation d'une interface se résout à la même instance.La configuration de cette instance peut se produire dans le constructeur de la classe ou vous pouvez implémenter IPartImportsSatisfiedNotification sur votre classe de service 'singleton', qui rappellera quand MEF aura fini de résoudre vos importations de classe.


La lecture de votre description mise à jour, il semble que vous ne pouvez pas configurer la classe dans son constructeur ou après ses importations ont été résolus, que vous avez besoin des informations contextuelles supplémentaires. Si tel est le cas, vous pouvez configurer la classe manuellement dans votre shell et ajouter manuellement l'exportation après sa création à l'aide de la méthode ComposeParts du conteneur. Cela fera de votre instance 'configurée' celle qui sera utilisée pour résoudre les balises [Export] que vous avez appliquées à la classe. Bien sûr, vous devrez le faire avant de construire quoi que ce soit d'autre à travers le conteneur qui dépend de l'instance.

+0

Je vais essayer, semble raisonnable :) – TimothyP

+0

Fonctionne comme un charme. J'ai utilisé Container.ComposeExportedValue (client); dans ma classe bootstrapper mef après que l'instance du client a été configurée. Maintenant les constructeurs du module prennent simplement un client :-) Merci! – TimothyP

Questions connexes