How to manage discovery and composition as 2 separate concerns?

為{幸葍}努か 提交于 2019-12-02 07:42:11

I think these concerns are already separated: discovery is handled by catalogs, and composition is done by export providers.

In the typical case, you just pass a catalog directly to the container and for convenience it will automatically take care of creating an CatalogExportProvider for it.

But you can also create one or more export providers yourself and pass them to the container with this constructor overload. (You may also have to set the SourceProvider to point back at the container after that, so that the export providers can use each other.)

You can create your own ExportProvider implementations, and they don't even have to be backed by catalogs.

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 { }

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);
}

...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();
}

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();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!