如何将现有实例添加到MEF目录中?

时间:2011-04-11 01:08:59

标签: mef catalog

我有一个对象实例,我希望最终得到一个包含该对象实例的MEF目录,并作为特定的接口类型导出。我怎么能这样做?

TypeCatalog在这里似乎不可行,因为(a)它创建一个新实例而不是使用现有实例,(b)它要求类型具有[Export]属性。在我的例子中,实例来自MEF的元数据系统,因此MEF创建了底层类型,我无法为其添加属性。

据我所知,通常的建议是,如果你有一个现有的实例,你应该把它添加到容器(例如通过CompositionBatch),而不是目录。但是当我添加这个实例时,我还要添加一个完整的AssemblyCatalog类型,所有这些都在同一个操作中。我还希望以后能够删除所有这些类型。将所有内容捆绑到AggregateCatalog中对我来说更有意义。这样,我可以在一个原子操作中添加程序集和实例,我可以用同样的方法再次删除它们。

例如:

// Bootstrapper code to initialize MEF:
public void Configure() {
    _selectedGameCatalog = new AggregateCatalog();
    var globalCatalog = new AggregateCatalog(_selectedGameCatalog);
    _container = new CompositionContainer(globalCatalog);
    // ... more MEF initialization ...
}

// Sometime later, I want to add more stuff to the MEF ecosystem:
public void SelectGame(Lazy<Game, IGameMetadata> entry) {
    var newCatalog = new AggregateCatalog();
    // Make the assembly available to import:
    newCatalog.Catalogs.Add(new AssemblyCatalog(entry.Value.GetType().Assembly));

    // I also want the metadata to be available to import:
    IGameMetadata metadata = entry.Metadata;
    newCatalog.Catalogs.Add(MakeCatalogFromInstance<IGameMetadata>(metadata));

    // Replace whatever game was selected before:
    _selectedGameCatalog.Catalogs.Clear();
    _selectedGameCatalog.Catalogs.Add(newCatalog);
}

我不知道该怎么做的部分是“MakeCatalogFromInstance”。如何创建包含现有实例的目录(注册为特定类型)?

或者,或者,如果我说这一切都错了,是否有更好的方法将整个目录同时插入到MEF中,并且能够之后再将它们全部拔掉并用其他东西替换它们?

2 个答案:

答案 0 :(得分:1)

我认为最好将类型添加到目录中,然后将实例添加到容器中。

目录包含零件定义。零件定义用于创建零件。 (其类型为ComposablePartDefinitionComposablePart。)因此,理论上您可以编写自己的目录和部件定义,在调用CreatePart时始终返回与实例对应的部件。但目录并没有真正用于这种方式。

答案 1 :(得分:1)

为了繁荣......

MEF从实际运行的对象实例(容器)中分离了要使用的类型信息(目录)的杂事。对我而言,这是一个逻辑上的说法,特别是当您在应用程序中设置更复杂的MEF环境时。

如果您希望能够动态“更改”容器,我建议您尝试使用分层容器。根目录/容器中填充了静态类型,任何子容器都可以填充游戏所需的每个特定元类型集。

希望它有所帮助, 马克