2013-06-05 10 views
9

An der Wurzel meiner Anwendung habe ich eine AggregateCatalog und CompositionContainer etwa so:Scope Definition in MEF mit CompositionScopeDefinition

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

Module Meine Anwendung Lasten bis die mehrere Exporte enthalten, wie sie in der Abbildung unten dargestellt. Ich möchte CompositionScopeDefinition verwenden, um die im Diagramm eingekreisten Exporte zu definieren.

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>(); 

Dies verursacht jedoch die folgende Ausnahme:

System.ComponentModel.Composition.ImportCardinalityMismatchException Nachricht aufgetreten = Keine Exporte wurden gefunden, dass das Spiel Einschränkung: ContractName MyNamespace. RequestListener RequiredTypeIdentity MyNamespace.RequestListener Innerexception:

Wie kann meine scoped Exporte mit CompositionScopeDefinition zu einem bestehenden AggregateCatalog hinzufügen und initialisieren sie meine vorhandenen CompositionContainer mit?

aktualisieren

Es scheint, dass das Problem ein AggregateCatalog verwenden. Wenn ich die CompositionScopeDefinition direkt dem CompositionContainer hinzufüge, funktioniert alles, aber das hindert mich daran, dem CompositionContainer andere Kataloge hinzuzufügen.

Antwort

2

Ich sprach mit den Jungs, die auf CodePlex auf MEF arbeiten. Dies war im Wesentlichen ihre Antwort:

// 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>(); 

Im Wesentlichen können Sie keine CompositionScopeDefinition innerhalb eines AggregateCatalog platzieren. So können Sie die Beziehung invertieren und eine CompositionScopeDefinition auf der Stammebene und mehrere AggregateCatalogs für jede Scope-Ebene haben, die Sie darzustellen versuchen. Das scheint großartig zu funktionieren. Sie erhalten außerdem den zusätzlichen Vorteil, einen einzigen CompositionContainer zu haben.

+0

Wie passe ich das mit Prism Bootstrapper? –