如何管理发现和组合为2个独立的顾虑吗?组合、顾虑、独立、发现

2023-09-03 08:00:32 作者:感觉不会再爱了

我已经建立了一个组装目录:

I have set up an assembly catalog:

  private CompositionContainer GetContainer() {
     // initialize directory info
     ExtensionDirectory = new DirectoryInfo(settings.ExtensionsPath);
     // directory catalog
     var dirCatalog = new DirectoryCatalog(ExtensionDirectory.FullName);

     return new CompositionContainer(dirCatalog);
  }

容器中的内容将加载在该目录中的所有组件预期。我并不想真正构成任何事情,因为我将与依赖注入的构造函数。

The contents of the container will load up all the assemblies in the directory as expected. I do not want to actually compose anything yet because I have constructors that will be injected with dependencies.

我想要做的就是使用 AssemblyCatalog 作为存储库;查询具体的出口,通过构造函数依赖,然后撰写的只有的参与这一过程的部分。

What I want to do is use the AssemblyCatalog as a repository; query for a specific export, pass the constructor dependency, then compose only the parts involved in this process.

据我了解,如果我叫

_container.ComposeParts(this);

...无需提供出口的 [ImportingConstructor] S,那么所有的部件将被列入 _container

...without providing exports for the [ImportingConstructor]s, then none of the parts would be included in the _container.

为了便于查询到容器上,我有一个方法,如下所示:

In order to facilitate queries to the container, I have a method as follows:

  public Lazy<IEntity> GetPart(Func<Lazy<IEntity, IEntityMetaData>, bool> selector) {
     var entity = _container.GetExports<IEntity, IEntityMetaData>()
                            .Where(selector)
                            .Select(e => e as Lazy<IEntity>)
                            .FirstOrDefault();

     return entity; // this will be passed up to the composition service
  }

看来, GetExports&LT; T,M&GT;()将不会返回包含出口的 [ImportingConstructor] 如果这将满足依赖性的部分不包括在容器

It seems that GetExports<T, M>() will not return an export containing an [ImportingConstructor] if the part which would satisfy the dependency is not included in the container.

我的做法是有一个支线集装箱/目录中处于较低水平;更高层次的组合服务将接收所有部件和组成最终目标。我决定在这个办法,所以我们就可以添加/扩展类型,将来可用目录中。

My approach is to have an extension container/catalog at a low level; a higher level composition service will receive all parts and compose the final object. I decided on this approach so we would be able to add/extend the types of catalogs available in the future.

推荐答案

为了满足需求,我创建了3类:

In order to satisfy the requirements, I created 3 classes:

public sealed class CompositionFactory {
  [Import("Provider")]
  private IProvider importProvider;

  /* MEF initialization */
}

[Export("Provider")]
public sealed class AssemblyProvider : IProvider {
  private CatalogExportProvider _provider;
}

internal sealed class ComposableAggregate { }

CompositionFactory 初始化MEF发现的 AssemblyProvider 。当提供初始化:

The CompositionFactory initializes MEF to discover the AssemblyProvider. When the provider initializes:

private CatalogExportProvider InitializeProvider() {
   // directory catalog
   var dirCatalog = new DirectoryCatalog(ExtensionDirectory.FullName);
   return new CatalogExportProvider(dirCatalog);
}

...我们返回一个 CatalogExportProvider 。我现在可以使用API​​将CompositionFactory:

...we return a CatalogExportProvider. I can now use an API to the CompositionFactory:

public ISomething GetSomething(string ContractName, object ContractParam) {
   // implementation
}

...来查询使用合同名称的正确组合的一部分:

...to query for the correct composable part using a contract name:

public ComposablePartDefinition GetPartDefinition(string ContractName) {
   return _provider.Catalog.Parts
                   .Where(p => p.ExportDefinitions
                                .Select(e => e.ContractName)
                                .Any(c => c == ContractName))
                   .FirstOrDefault();
}

这项工作,然后在ComposableAggregate辅助类完成的:

The work is then completed in the ComposableAggregate helper class:

internal ISomething Value {
   get {
      return _container.GetExport<IEntity>(_contractName).Value;
   }
}

private CompositionBatch CreateBatch() {
   CompositionBatch batch = new CompositionBatch();
   // create composable part from definition
   ComposablePart importDef = CreatePart(_contractName);
   batch.AddPart(importDef);
   return batch;
}

private ComposablePart CreatePart(string ContractName) {
   // get part definition from catalog
   return _provider.GetPartDefinition(ContractName).CreatePart();
}