2009-06-22 8 views
5

Ich muss einige Erweiterungspunkte zu unserem bestehenden Code hinzufügen, und ich habe MEF als eine mögliche Lösung betrachtet. Wir haben eine IRandomNumberGenerator-Schnittstelle mit einer Standardimplementierung (ConcreteRNG), die wir gerne austauschen würden. Das klingt nach einem idealen Szenario für MEF, aber ich habe Probleme mit der Instanziierung der Zufallsgeneratoren. Unsere aktuellen Code wie folgt aussehen:Kann ich die Erstellung von Objekten mithilfe von MEF steuern?

public class Consumer 
{ 
    private List<IRandomNumberGenerator> generators; 
    private List<double> seeds; 

    public Consumer() 
    { 
     generators = new List<IRandomNumberGenerator>(); 
     seeds = new List<double>(new[] {1.0, 2.0, 3.0}); 

     foreach(var seed in seeds) 
     { 
      generators.Add(new ConcreteRNG(seed)); 
     } 
    } 
} 

Mit anderen Worten, die Verbraucher zum Instanziieren der RNGs verantwortlich ist es braucht, einschließlich der Bereitstellung von den Samen, die jede Instanz erfordert.

Was ich tun möchte, ist die konkrete RNG-Implementierung von MEF entdeckt und instanziiert (mit dem DirectoryCatalog). Ich bin mir nicht sicher, wie ich das erreichen soll. Ich könnte eine Generators-Eigenschaft verfügbar machen und sie als [Import] markieren, aber wie stelle ich die erforderlichen Seeds bereit?

Gibt es einen anderen Ansatz, den ich vermisse?

Antwort

5

Derzeit gibt es keine direkte Möglichkeit, dies in MEF zu tun, aber das MEF-Team erwägt Unterstützung in v.Next. Sie möchten im Wesentlichen mehrere Instanzen derselben Implementierung erstellen, die traditionell mit einem Factory-Muster erstellt wurde. So ein Ansatz, den Sie verwenden können, ist so etwas wie:

public interface IRandomNumberGeneratorFactory 
{ 
    IRandomNumberGenerator CreateGenerator(int seed); 
} 

[Export(typeof(IRandomNumberGeneratorFactory))] 
public class ConcreateRNGFactory : IRandomNumberGeneratorFactory 
{ 
    public IRandomNumberGenerator CreateGenerator(int seed) 
    { 
    return new ConcreateRNG(seed); 
    } 
} 

public class Consumer 
{ 
    [Import(typeof(IRandomNumberGeneratorFactory))] 
    private IRandomNumberGeneratorFactory generatorFactory; 
    private List<IRandomNumberGenerator> generators;  
    private List<double> seeds;  

    public Consumer()  
    { 
    generators = new List<IRandomNumberGenerator>(); 
    seeds = new List<double>(new[] {1.0, 2.0, 3.0}); 

    foreach(var seed in seeds) 
    {    
     generators.Add(generatorFactory.CreateGenerator(seed)); 
    } 
    } 
} 
+0

Danke Wes. Ich hatte einen Fabrikansatz in Betracht gezogen, war aber wegen der Tatsache, dass ich eine generische Fabrik haben wollte, die eine Instanz des Typs IRandomNumberGenerator erstellen würde, der von MEF entdeckt wurde, hängengeblieben. Wenn Sie noch einmal darüber nachdenken, scheint Ihre Herangehensweise nicht viel zusätzliche Arbeit zu sein - nochmals vielen Dank. – Akash

+1

Ich habe das jetzt funktioniert. Ich kann es vereinfacht ein wenig durch eine statische Factory-Methode auf ConcreteRNG Bereitstellung: [Export (typeof (Func ))] public static Nur-Lese-Func Create = seed => new ConcreteRNG (Samen) ; – Akash

+0

Ja exportieren Sie eine Funktion selbst ist auch eine andere vereinfachte Möglichkeit, um zu bekommen, was Sie wollen. Ich habe auch festgestellt, dass Sie, wenn Sie diesen Import im Konstruktor verwenden möchten, einen Konstruktorimport durchführen müssen, da dieser Import, wie ich gezeigt habe, nicht vor der Konstruktion des Objekts gesetzt wird. –

0

Ich glaube, das ist es, was die Lazy Exports Funktion für ist. Von dieser Seite:

[Import] 
public Export<IMessageSender> Sender { get; set; } 

In diesem Fall sind Sie Opt-in für die Verzögerung dieser Instanziierung, bis Sie tatsächlich die Umsetzung Instanz benötigen. Verwenden Sie die Methode [Export.GetExportedObject()], um die Instanz anzufordern. Beachten Sie, dass diese Methode niemals als eine Factory von Implementierungen von T fungiert. Wenn Sie sie mehrmals aufrufen, wird dieselbe Objektinstanz zurückgegeben, die beim ersten Aufruf zurückgegeben wurde.

+0

Scott, ich brauche mehrere Instanzen von IRandomNumberGenerator. Dein Kommentar deutet darauf hin, dass ich jedes Mal die gleiche Instanz bekomme. Fehle ich etwas? – Akash

+0

Entschuldigung, ich habe diesen Teil verpasst. In diesem Fall denke ich, dass Sie das Fabrikmuster brauchen. –

4

MEF-Vorschau 8 hat experimentelle Unterstützung dafür, obwohl es noch nicht in System.ComponentModel.Composition.dll enthalten ist. Weitere Informationen finden Sie unter this blog post.

Sie müssen die MEF-Quellen herunterladen und die Lösung erstellen. Im Ordner finden Sie die Baugruppe Microsoft.ComponentModel.Composition.DynamicInstantiation.dll. Fügen Sie einen Verweis auf diese Assembly und fügen eine dynamische Instanziierung Anbieter zu Ihrem Container wie folgt aus:

var catalog = new DirectoryCatalog("."); 
var dynamicInstantiationProvider = new DynamicInstantiationProvider(); 
var container = new CompositionContainer(catalog, dynamicInstantiationProvider); 
dynamicInstantiationProvider.SourceProvider = container; 

Jetzt werden Ihre Teile der Lage sein, eine PartCreator<Foo> zu importieren, wenn sie Foo Teile dynamisch erstellen müssen. Der Vorteil gegenüber dem Schreiben Ihrer eigenen Fabrikklasse ist, dass dies transparent für die Importe von Foo und die Importe der Importe und so weiter sorgt.

bearbeiten:

  • in MEF Preview 9PartCreator wurde ExportFactory umbenannt, aber es ist nur in der Silverlight-Ausgabe enthalten.
  • in MEF 2 Preview 2, ExportFactory wurde für die Desktop-Edition enthalten. So wird ExportFactory wahrscheinlich Teil der nächsten .NET Framework-Version nach .NET 4.0 sein.
+0

Danke, ich werde diesen Link verfolgen. – Akash

Verwandte Themen