我已经设置了一个程序集目录:
private CompositionContainer GetContainer() {
// initialize directory info
ExtensionDirectory = new DirectoryInfo(settings.ExtensionsPath);
// directory catalog
var dirCatalog = new DirectoryCatalog(ExtensionDirectory.FullName);
return new CompositionContainer(dirCatalog);
}
容器的内容将按预期加载目录中的所有程序集。我不想实际编写任何东西,因为我的构造函数会注入依赖项。
我想要做的是使用AssemblyCatalog
作为存储库;查询特定导出,传递构造函数依赖项,然后仅编写 此过程中涉及的部分。
根据我的理解,如果我打电话
_container.ComposeParts(this);
...没有为[ImportingConstructor]
提供导出,则_container
中不会包含任何部分。
为了便于查询容器,我有一个方法如下:
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<T, M>()
似乎不会返回包含[ImportingConstructor]
的导出。
我的方法是将扩展容器/目录放在较低的水平;更高级别的合成服务将接收所有部分并组成最终对象。我决定使用这种方法,以便我们能够添加/扩展将来可用的目录类型。
答案 0 :(得分:1)
我认为这些问题已经分开:发现由目录处理,组成由出口提供商完成。
在典型情况下,您只需将目录直接传递给容器,为方便起见,它会自动为其创建CatalogExportProvider。
但您也可以自己创建一个或多个导出提供程序,并使用this constructor overload将它们传递给容器。 (在此之后,您可能还必须将SourceProvider设置为指向容器,以便导出提供程序可以相互使用。)
您可以创建自己的ExportProvider实现,甚至不必由目录支持。
答案 1 :(得分:0)
为了满足要求,我创建了3个类:
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
。提供者初始化时:
private CatalogExportProvider InitializeProvider() {
// directory catalog
var dirCatalog = new DirectoryCatalog(ExtensionDirectory.FullName);
return new CatalogExportProvider(dirCatalog);
}
...我们返回CatalogExportProvider
。我现在可以使用API到CompositionFactory:
public ISomething GetSomething(string ContractName, object ContractParam) {
// implementation
}
...使用合同名称查询正确的可组合零件:
public ComposablePartDefinition GetPartDefinition(string ContractName) {
return _provider.Catalog.Parts
.Where(p => p.ExportDefinitions
.Select(e => e.ContractName)
.Any(c => c == ContractName))
.FirstOrDefault();
}
然后在ComposableAggregate帮助程序类中完成工作:
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();
}