2013-06-05 81 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? –