2013-06-05 20 views
9

Alla base della mia candidatura ho un AggregateCatalog e un CompositionContainer in questo modo:Definizione Scope in MEF con CompositionScopeDefinition

AggregateCatalog aggregateCatalog = new AggregateCatalog(); 
CompositionContainer compositionContainer = new CompositionContainer(aggregateCatalog); 

miei carichi applicativi dei moduli che contengono diversi esportazioni, come indicato nello schema seguente. Voglio usare CompositionScopeDefinition per esplorare le esportazioni cerchiate nel diagramma.

Module Export Diagram

See here for the class definitions.

// Create CompositionScopeDefinition. 
TypeCatalog globalParts = new TypeCatalog(typeof(RequestListener)); 
TypeCatalog scopedParts = new TypeCatalog(typeof(RequestHandler), typeof(DataAccessLayer), typeof(Logger), typeof(DatabaseConnection)); 
CompositionScopeDefinition compositionScopeDefinition = new CompositionScopeDefinition(
    globalParts, 
    new[] { new CompositionScopeDefinition(scopedParts, null) }); 

// Register CompositionScopeDefinition. 
aggregateCatalog.Catalogs.Add(compositionScopeDefinition); 

// Create an instance of RequestListener. 
RequestListener requestListener = compositionContainer.GetExportedValue<RequestListener>(); 

Tuttavia, questo fa sì che la seguente eccezione:

System.ComponentModel.Composition.ImportCardinalityMismatchException verificato Messaggio = Nessun esportazioni sono stati trovati che corrispondono al vincolo: ContractName MyNamespace. RequestListener RequiredTypeIdentity MyNamespace.RequestListener InnerException:

Come posso aggiungere i miei esportazioni con ambito utilizzando CompositionScopeDefinition a un AggregateCatalog esistente e inizializzare loro usando il mio CompositionContainer esistente?

Aggiornamento

Sembra che il problema utilizzando un AggregateCatalog. Se aggiungo la CompositionScopeDefinition a CompositionContainer direttamente tutto funziona, ma questo non mi consente di aggiungere altri cataloghi a CompositionContainer.

risposta

2

Ho parlato con i ragazzi che lavorano su MEF su CodePlex. Questa era essenzialmente la loro risposta:

// Handy extension methods for dealing with CompositionScopeDefinition (Not relevant to this answer but useful). 
public static class ComposablePartCatalogExtensions 
{ 
    public static CompositionScopeDefinition AsScope(this ComposablePartCatalog catalog, params CompositionScopeDefinition[] children) 
    { 
     return new CompositionScopeDefinition(catalog, children); 
    } 

    public static CompositionScopeDefinition AsScopeWithPublicSurface<T>(this ComposablePartCatalog catalog, params CompositionScopeDefinition[] children) 
    { 
     IEnumerable<ExportDefinition> definitions = catalog.Parts.SelectMany((p) => p.ExportDefinitions.Where((e) => e.ContractName == AttributedModelServices.GetContractName(typeof(T)))); 
     return new CompositionScopeDefinition(catalog, children, definitions); 
    } 
} 

AggregateCatalog aggregateCatalog = new AggregateCatalog(); 
AggregateCatalog childAggregateCatalog = new AggregateCatalog(); 
CompositionScopeDefinition compositionScopeDefinition = aggregateCatalog.AsScope(childAggregateCatalog.AsScope()); 
CompositionContainer compositionContainer = new CompositionContainer(compositionScopeDefinition); 

TypeCatalog globalParts = new TypeCatalog(typeof(RequestListener)); 
TypeCatalog scopedParts = new TypeCatalog(typeof(RequestHandler), typeof(DataAccessLayer), typeof(Logger), typeof(DatabaseConnection)); 

aggregateCatalog.Catalogs.Add(globalParts); 
childAggregateCatalog.Catalogs.Add(scopedParts); 

RequestListener requestListener = compositionContainer.GetExportedValue<RequestListener>(); 

In sostanza non si può mettere un CompositionScopeDefinition all'interno di un AggregateCatalog. In questo modo è possibile invertire la relazione e avere una CompositionScopeDefinition al livello principale e più AggregateCatalog per ogni livello di ambito che si sta tentando di rappresentare. Questo sembra funzionare alla grande. Hai anche il vantaggio di avere un singolo CompositionContainer.

+0

Come si inserisce questo con Prism Bootstrapper? –