2009-05-05 5 views
2

Je tente d'utiliser la stratégie de création de pièces partagées pour une exportation MEF. Cependant, cela ne semble pas fonctionner comme je le pensais. Je fais la composition deux fois dans mon application et chaque fois obtenir une nouvelle copie de l'objet. Je l'ai prouvé en ajoutant un compteur d'instance à l'instanciation d'objetStratégie de création MEF

static int instCount = 0; 

    public FakeAutocompleteRepository() 
    { 
     instCount++; 
     ... 
    } 

et de lancer tout cela dans le débogage. En effet, la deuxième fois que je fais une composition que je reçois une nouvelle copie du FakeAutocompleteRepository avec instCount = 2. La section d'exportation contient

[PartCreationPolicy(CreationPolicy.Shared)] 
[Export(typeof(IAutocompleteRepository))] 
[ExportMetadata("IsTesting", "True")] 
class FakeAutocompleteRepository : IAutocompleteRepository 
{ ... } 

Y at-il une astuce pour obtenir la même instance pour les demandes de subsiquent? Dans le cas où il est quelque chose que je fais au cours de la composition est ce que je fais que

var catalog = new AggregateCatalog(); 
       catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly())); 
       catalog.Catalogs.Add(new DirectoryCatalog(".")); 
       var container = new CompositionContainer(catalog); 
       var batch = new CompositionBatch(); 
       batch.AddPart(this); 
       container.Compose(batch); 


       if (null != ConfigurationSettings.AppSettings["IsTesting"] && bool.Parse(ConfigurationSettings.AppSettings["IsTesting"])) 
        repository = container.GetExports<IAutocompleteRepository>().Where(expDef => expDef.Metadata.Keys.Contains("IsTesting")).Single().GetExportedObject(); 

Fondamentalement, je suis en train de forcer une composition spécifique au cours des essais. Si vous avez une meilleure idée pour tester ces compositions, alors je suis tout ouïe.

Répondre

3

Je ne vois rien de particulier dans votre code qui provoquerait la création de plus d'un de vos composants. Créez-vous un conteneur différent pour chaque composition? Si vous êtes, c'est pourquoi vous obtenez des instances distinctes.

En ce qui concerne la façon de combiner la composition et les tests unitaires en général, il y a une discussion de ce here.

+0

Je crée totalement un nouveau conteneur à chaque fois. Existe-t-il un moyen d'interroger les conteneurs actifs ou faut-il créer une instance par application quelque part? – stimms

+0

Il n'existe aucun moyen de rechercher des conteneurs actifs. Je devrais en savoir plus sur votre demande pour vous donner des conseils sur ce que vous devriez faire. A quoi servent les multiples compositions? –

+0

Ce que vous pouvez faire est d'exporter votre conteneur de votre hôte et de l'importer chaque fois que vous voulez l'utiliser. Je ne l'ai pas fait, mais je pense que je l'ai vu dans l'exemple du jeu MefShapes ... –

2

Ce que j'ai fait pour les tests unitaires était d'éviter la composition. Par exemple (j'utilise WPF et MVVM ici), disons que vous voulez tester cette ViewModel:

[Export("/MyViewModel")] 
public class MyViewModel 
{ 
    [ImportingConstructor] 
    public MyViewModel(
     [Import("/Services/LoggingService")] ILoggingService l) 
    { 
     logger = l; 
    } 

    private ILoggingService logger { get; set; } 

    /* ... */ 
} 

Je ne veux pas instancier le service d'enregistrement complet à chaque fois que je fais un test unitaire, donc j'ai une classe MockLoggingService qui implémente ILoggingService et elle avale juste tous les messages de journal, (ou vérifie que les messages appropriés sont générés, si vous vous souciez). Ensuite, je peux le faire dans mon test unitaire:

MyViewModel target = new MyViewModel(new MockLoggingService());