2012-01-25 47 views
5

Używam hierarchii kontenerów do kontrolowania czasu życia części IDisposable. Kontener potomny jest dołączany do przefiltrowanego katalogu zawierającego niepodzielone części. Oto fragment kodu:Hierarchia kontenerów MEF i 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); 
    } 
} 

(Klasa FilteredCatalog jest taka sama, jak wspomniano w dokumentacji MEF).

GetExport nie generuje wyjątku niezgodności liczności, który wskazuje, że nie ma żadnych niejednoznaczności (znaleziono dokładnie jeden eksport). Ale ku mojemu zaskoczeniu, GetExports() zwraca 2 leniwy eksport zamiast 1.

Czy to błąd czy to zachowanie jest zgodne z projektem? Jak mogę skonfigurować kontener podrzędny, aby GetExports zwrócił jeden eksport w tym przykładzie?

+0

czy cokolwiek importuje 'ITest'? –

+0

Nie, opublikowałem tutaj cały fragment. Usuwany jest tylko kod klasy usings i FilteredCatalog. – yallie

Odpowiedz

2

Jest to znane ograniczenie hierarchii kontenerów w MEF przy użyciu filtrowanych katalogów. Wierzę, (ale nie może potwierdzić, teraz), że ustalenie źródła importu:

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

powinien dać żądane zachowanie (ale tylko w MEF2/.NET 4.5 Preview Developer).

Mam nadzieję, że to pomoże!

+0

Dzięki za odpowiedź! Czy ta funkcja jest dostępna w wydaniu MEF2 Preview5 opublikowanym w CodePlex? – yallie

+0

Ta funkcja działa zgodnie z opisem i jest rzeczywiście dostępna w Preview10 MEF2 opublikowanej w CodePlex. Jednak ustawienie Source na ImportSource.Local spowoduje pobranie części tylko z kontenera podrzędnego, więc nie można zaimportować w ten sposób niepodzielonych części. Próbowałem wykonać wszystkie wyeksportowane części (zarówno udostępnione, jak i niewspólne), ale bez duplikatów. – yallie

+0

Ah - Widzę problem, przepraszam. Również w wersji 4.5 DP mamy 'CompositionScopeDefinition', która ma większe szanse na zajęcie się tą sprawą - patrz: http://blogs.msdn.com/b/bclteam/archive/2011/12/19/sharing-with-compositionscopedefinition-in -mef2-alok.aspx –