2013-06-05 124 views
9

在我的應用程序的根我有一個AggregateCatalog和CompositionContainer中,像這樣:定義範圍,MEF與CompositionScopeDefinition

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

我的應用程序加載了包含幾個出口如下面的圖中的模塊。我想使用CompositionScopeDefinition來限制圖中圈出的導出。

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

然而,這會導致以下情況除外:

System.ComponentModel.Composition.ImportCardinalityMismatchException發生消息=沒有出口找到匹配的是約束: ContractName MyNamespace。 RequestListener RequiredTypeIdentity MyNamespace.RequestListener的InnerException:

如何添加使用CompositionScopeDefinition我的作用域出口到現有AggregateCatalog並使用我現有的CompositionContainer中初始化呢?

更新

看來,使用AggregateCatalog問題。如果我直接將CompositionScopeDefinition添加到CompositionContainer中,但是這會阻止我將其他目錄添加到CompositionContainer中。

回答

2

我與在CodePlex上從事MEF工作的人交談過。這基本上是他們的答案:

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

實質上,您不能將CompositionScopeDefinition放置在AggregateCatalog中。因此,您可以反轉關係,並在根級別有一個CompositionScopeDefinition,並且您想要表示的每個作用域級別都有多個AggregateCatalog。這似乎很好。您還可以獲得單個CompositionContainer的額外好處。

+0

我該如何適應Prism Bootstrapper? –