2012-01-25 18 views
5

IDisposableパーツの有効期間を制御するためにコンテナ階層を使用しています。子コンテナは、非共有部分を含むフィルタされたカタログに添付されます。MEFコンテナ階層とGetExports <T>

[Export(typeof(ITest)), PartCreationPolicy(CreationPolicy.NonShared)] 
class Test : ITest, IDisposable 
{ 
    public void Dispose() {} 
} 

public interface ITest {} 

class Program 
{ 
    static void Main() 
    { 
    // parent container to hold shared disposable parts 
    var cat = new AssemblyCatalog(typeof(Program).Assembly); 
    var parent = new CompositionContainer(cat); 

    // child container to hold non-shared disposable parts 
    var nsCat = CreateNonSharedPartCatalog(cat); 
    var child = new CompositionContainer(nsCat, parent); 

    // no cardinality mismatch exception: exactly one export found 
    var exp = child.GetExport<ITest>(); 

    // lazy exports: count == 2 -- why? 
    var exports = child.GetExports<ITest>(); 
    Console.WriteLine("Exports count = {0}", exports.Count()); 
    } 

    static ComposablePartCatalog 
    CreateNonSharedPartCatalog(ComposablePartCatalog cat) 
    { 
    return new FilteredCatalog(cat, 
     def => def.Metadata.ContainsKey(
     CompositionConstants.PartCreationPolicyMetadataName) && 
     ((CreationPolicy)def.Metadata[ 
     CompositionConstants.PartCreationPolicyMetadataName]) == 
      CreationPolicy.NonShared); 
    } 
} 

(FilteredCatalogクラスはMEFドキュメントに記載されているものと同じです)。

GetExportは、あいまいさがないことを示すカーディナリティ不一致例外をスローしません(まさに1つのエクスポートが見つかります)。しかし、驚いたことに、GetExports()は1ではなく2つの遅延エクスポートを返します。

これはバグですか?このサンプルでGetExportsが1つのエクスポートを返すように子コンテナを設定するにはどうすればよいですか?

+0

は「ITest」をインポートするものですか? –

+0

いいえ、ここに完全なスニペットを掲載しました。 usingsおよびFilteredCatalogクラスコードのみが削除されます。 – yallie

答えて

2

これは、フィルタリングされたカタログを使用するMEFのコンテナ階層の既知の制限です。私は信じている(しかし、今は確認できない)というインポートソースの設定:

[ImportMany(Source=ImportSource.Local)] 
public IEnumerable<ITest> Tests { get; set; } 

は、あなたが望む行動(だけでMEF2/.NET 4.5の開発者プレビュー)を与える必要があります。

希望すると便利です。

+0

返信いただきありがとうございます!この機能はCodePlexで公開されているMEF2 Preview5で利用できますか? – yallie

+0

この機能は、説明したとおりに動作し、実際にCodePlexで公開されているMEF2 Preview5で利用できます。ただし、SourceをImportSource.Localに設定すると、子コンテナからのみパーツが引き出されるので、非共有パーツはこのようにインポートできません。私がしようとしていたのは、すべてのエクスポートされたパーツ(共有と非共有の両方)を取得することでしたが、重複はありませんでした。 – yallie

+0

ああ - 私は問題を見る、ごめんなさい。また、4.5 DPでは、このケースを処理するより良い機会を持つ 'CompositionScopeDefinition'があります - http://blogs.msdn.com/b/bclteam/archive/2011/12/19/sharing-with-compositionscopedefinition-inを参照してください。 -mef2-alok.aspx –