2012-03-08 1 views
0

私は、アセンブリのカタログを設定している:発見と構成を2つの別々の懸念事項として管理するにはどうすればよいですか?

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

    return new CompositionContainer(dirCatalog); 
    } 

予想通り、コンテナの中身は、ディレクトリ内のすべてのアセンブリをロードします。依存関係が注入されるコンストラクタがあるため、実際には何も作成したくありません。

私がしたいことは、AssemblyCatalogをリポジトリとして使用することです。特定のエクスポートを照会し、コンストラクターの依存関係を渡した後、のみをこのプロセスに関与する部分を構成します。私が理解から

、私は[ImportingConstructor]のための輸出を設けることなく、...

_container.ComposeParts(this); 

をコールした場合、その部品はどれも_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

要件を満たすために、私は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 { } 

CompositionFactoryAssemblyProviderを発見するためにMEFを初期化します。プロバイダの初期化時:

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

...我々はCatalogExportProviderを返します。 CompositionFactoryへのAPIを使用できるようになりました。

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

私はこれらの懸念事項が既に分かれていると思います。発見はカタログによって処理され、構成はエクスポートプロバイダによって行われます。

典型的なケースでは、カタログに直接コンテナを渡すだけです。便宜上、自動的にCatalogExportProviderを作成します。

しかし、自分で1つ以上のエクスポートプロバイダを作成して、this constructor overloadでコンテナに渡すこともできます。

は、あなたがあなた自身のExportProvider実装を作成することができます(エクスポート・プロバイダーが互いを使用できるように、また、その後の容器に戻って指すようにSourceProviderを設定する必要があります)、そして彼らもする必要はありません。カタログに裏打ちされています。

+0

はい、彼らが分離されている - 多分よりよい用語は独立していることでしょう。私たちは、構成サービスの拡張となるカタログを持っています。エンティティのサービスを照会すると、完全に構成されたエンティティが返されます。 – IAbstract

+0

私はMEFのConventionモデルを探求するつもりだと思います。私は、部品の発見方法をより柔軟にすると思います。 – IAbstract

+0

実際には、私はちょうどあなたのブログを見つけました:http://mindinthewater.blogspot.com/2011/03/mef-attribute-less-registration.html – IAbstract