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

4
我有一个对象实例,希望最终得到一个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中,并具有以后卸载它们并替换为其他内容的能力?

可能是一个答案 https://dev59.com/12435IYBdhLWcg3w0Trc - Trident D'Gao
2个回答

1

为了繁荣...

MEF将使用的信息类型(目录)的任务与实际运行的对象实例(容器)分开。对我来说,这是一个逻辑决策,特别是当您在应用程序中设置更复杂的MEF环境时。

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

希望有所帮助, 马克


1

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

目录包含部件定义。部件定义用于创建部件。(这些类型为ComposablePartDefinitionComposablePart。)因此,您可以理论上编写自己的目录和部件定义,当调用CreatePart时,始终返回与实例相对应的部分。但目录并不是真正设计成这样使用的。


1
我发现MEF将声明“这里可以获取X”的责任分散在两个完全不同的类中非常奇怪。如果你想以一种方式使用它(延迟初始化),你必须使用Catalog;如果你想以另一种方式使用它(现有实例),你必须使用Container。为什么它会有这样一个泄漏的抽象层? - Joe White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接