2016-04-26 6 views
1

ich ein paar Klassen ähnlich wie diese haben ...MEF ComposeParts Erstellen von Klassen nicht die Parameter, die injiziert werden müssen

[Export(typeof (IMessageReader))] 
public class DropboxFolderWatchMessageReader : IMessageReader 

und eine Vorlese-Klasse wie folgt ...

public class MessageReader 
{ 
    [ImportMany(typeof(IMessageReader))] 
    private List<IMessageReader> readers; 

    public List<Message> GetMessages() 
    { 
     var result = new List<Message>(); 
     readers.ForEach(r => result.AddRange(r.GetMessages())); 

     return result; 
    } 
} 

Meine Arbeitseinheit tut dies ...

public IEnumerable<Message> FetchMessages() 
{ 
    var reader = new MessageReader(); 
    MefComposer.Container.ComposeParts(reader); 

    var messages = reader.GetMessages(); 
    var result = AddMessages(messages); 

    return result; 
} 

In meiner ersten Iteration, das ist alles, um es dort war und es funktionierte gut.

Dann hatte ich meine Botschaft Leser bekommen ein bisschen mehr zu tun und das wiederum, ich meine den Konstrukteuren Parameter übergeben werden benötigt ...

public DropboxFolderWatchMessageReader(IConfig config) 
{ 
    //... 
} 

Als ich versuchte, meinen Code, den ich zu laufen habe eine Nachricht bekommen, dass meine Leser nicht erstellt werden konnten, da sie keinen Standardkonstruktor mehr hatten. Ich musste einen einzelnen Konstruktor mit dem [ImportingConstructorAttribute] schmücken. Also, ich fügte hinzu, dass ...

[System.ComponentModel.Composition.ImportingConstructorAttribute] 
public DropboxFolderWatchMessageReader(IConfig config) 
{ 
    //... 
} 

Nun kompiliert und läuft in Ordnung, aber die readers Sammlung ist immer leer.

In anderen Klassen, die in ihren Konstruktoren den gleichen Typ haben, wird das Objekt von Unity injiziert. Dies scheint nicht in meinem MEF-Code zu geschehen.

Also, auf die Frage ...

Wie bekomme ich das System:

  • Inject IConfig in den Konstrukteuren meiner Leser Klassen
  • die Leser Sammlung Zwingen zurück zu gehen mit meinen exportierten Leserklassen bevölkert zu sein, so wie es war.

Antwort

1

Ich habe ImportConstructor nie mit Feldebene Importe gemischt, obwohl ich denke, es würde funktionieren. (Wie lange Sie brauchen Sie nicht das Feld im Konstruktor oder eine Methode aus der Konstruktor aufgerufen.)

Meine allgemeine Empfehlung ist, nicht zu mischen, einen Konstruktor was wie:

[System.ComponentModel.Composition.ImportingConstructorAttribute] 
public DropboxFolderWatchMessageReader(IConfig config, [ImportMany(typeof(IMessageReader))] 
IEnumerable<IMessageReader> readers;) 
{ 
    this.reader = readers.ToList(); 
    // rest of body 
} 

Wenn Sie brauchen Um die Methoden zu mischen, aber Leser bei der Initialisierung des Objekts zu verwenden, können Sie die Schnittstelle IPartImportsSatisfiedNotification wie folgt implementieren:

class DropboxFolderWatchMessageReader : IPartImportsSatisfiedNotification 
{ 
    [ImportMany(typeof(IMessageReader))] 
    private List<IMessageReader> readers; 

    [System.ComponentModel.Composition.ImportingConstructorAttribute] 
    public DropboxFolderWatchMessageReader(IConfig config) 
    { 
     // empty body. readers still null here 
    } 

    public void OnImportsSatisfied() 
    { 
     // old constructor body. 
     // it's safe to use readers here as all imports have been satisfied 
    } 
}