使用运行时定义的合同名称组合导入

本文关键字:组合 导入 合同 运行时 定义 | 更新日期: 2023-09-27 18:19:52

我有一个MEF导出,如下所示:

public interface IMyInterface { }
public interface IInterfaceData
{
    string[] Data { get; }
}
[Export("MyContractName", typeof(IMyInterface))]
[ExportMetadata("Data", "SomeData", IsMultiple = true)]
public class MyInterfaceClass : IMyInterface  { }

然后我导入使用:

public class MyClass {
     [ImportMany("MyContractName", typeof(IMyInterface))]
     private IEnumerable<Lazy<IMyInterface, IInterfaceData>> _operations;
     private CompositionContainer _container; 
     private void Compose() {
         var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
         _container = new CompositionContainer(catalog);
         _container.ComposeParts(this);
     }
 }

这很好用。但是,我希望能够在运行时使用基于当前执行的业务逻辑的约定名称来编写导入。换句话说,我希望能够导入一个可变的合同名称。我可以通过这样做来绕过这个问题:

 private void Compose() {
      var contractName = "MyContractName";  // note this would be determined at run-time
      var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
      _container = new CompositionContainer(catalog);
      var foundExports = _container.GetExports<IMyInterface, IInterfaceData>(contractName);         
      _operations = foundExports; // set manually
 }

我非常乐意这样做。但是,现在没有理由使用[ImportMany]属性,我也不能再使用ComposeParts()了。我希望在整个项目中保持一致(为了我和我的团队),并希望能够依赖MEF属性、Compose()/ComposeParts()或两者。

是否有其他方法可以定义Import属性,以便调用_container.Compose()时考虑运行时定义的约定名称?也许出口需要更改,或者MEF框架中有其他内容可供我使用(按属性)?

*我甚至不确定这是否"正确"。即使确实有效。如果我试图保持所有事情的一致性,那就感觉很草率。

使用运行时定义的合同名称组合导入

这可以通过在容器上直接使用CompositionBatch来完成。

var batch = new CompositionBatch();
// Add the export to the batch via method or object referebce
batch.AddExport(new Export(name, partFactory));
batch.AddExport(new Export(part.Name, () => part));
// Compose into your CompositionContainer
_container.Compose(batch);
private MyClass PartFactory()
{ 
    // TODO: create the part to export..
}

注意,对于container对象,可以在构造过程中使用CompositionOptions.ExportCompositionService导出容器本身,从而允许

[Import] CompositionContainer _container;