2009-06-22 13 views
5

Potrzebuję dodać kilka punktów rozszerzeń do naszego istniejącego kodu i szukałem MEF jako możliwego rozwiązania. Mamy interfejs IRandomNumberGenerator z domyślną implementacją (ConcreteRNG), którą chcielibyśmy zamienić. Brzmi to jak idealny scenariusz dla MEF, ale mam problemy ze sposobem tworzenia instancji generatorów liczb losowych. Nasz aktualny kod wygląda następująco:Czy mogę kontrolować tworzenie obiektów za pomocą MEF?

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

Innymi słowy, gdy konsument jest odpowiedzialny za utworzenie wystąpienia RNGs potrzebuje, w tym zapewnienie, że każde ziarno instancja wymaga.

Chciałbym, aby konkretna implementacja RNG została odkryta i utworzona przez MEF (przy użyciu katalogu DirectoryCatalog). Nie jestem pewien, jak to osiągnąć. Mogę narazić własność Generatorów i oznaczyć ją jako [Import], ale jak mam dostarczyć wymagane nasiona?

Czy istnieje inne podejście, którego mi brakuje?

Odpowiedz

5

Obecnie nie ma bezpośredniego sposobu, aby to zrobić w MEF, ale zespół MEF rozważa wsparcie dla tego w v.Następnym. Zasadniczo chcesz utworzyć wiele instancji tej samej implementacji, która jest tradycyjnie wykonywana przy użyciu wzorca Factory. Więc jedno podejście można użyć coś jak:

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

Dzięki Wes. Zastanawiałem się nad podejściem fabrycznym, ale utknąłem z powodu faktu, że chciałem generyczną fabrykę, która stworzyła instancję dowolnego typu IRandomNumberGenerator odkrytego przez MEF. Myśląc o tym jeszcze raz, twoje podejście nie wydaje się zbyt dużą ilością pracy - jeszcze raz dziękuję. – Akash

+1

Mam to teraz działa. Uprośniłem to nieco, dostarczając statyczną metodę fabryczną na ConcreteRNG: [Eksport (typeof (Func ))] public static readonly Func Create = seed => new ConcreteRNG (seed) ; – Akash

+0

Tak, eksportuj samą funkcję, to także inny uproszczony sposób na uzyskanie tego, co chcesz. Zauważyłem też, że jeśli chcesz użyć tego importu w konstruktorze, musisz uczynić go importem konstruktora, ponieważ ten import, jak pokazałem, nie zostanie ustawiony przed budową obiektu. –

0

Wierzę, że to, co jest cechą Lazy Exports dla. Od tej strony:

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

w tym przypadku są opt-in do opóźniania tej instancji aż rzeczywiście trzeba instancję wdrożenia. Aby zażądać wystąpienia, użyj metody [Export.GetExportedObject()]. Należy pamiętać, że ta metoda nigdy nie będzie działała jako fabryka implementacji T, więc wywołanie jej wiele razy zwróci tę samą instancję obiektu zwróconą przy pierwszym wywołaniu.

+0

Scott, potrzebuję wielu instancji IRandomNumberGenerator. Twój komentarz sugeruje, że za każdym razem otrzymam tę samą instancję. Czy czegoś brakuje? – Akash

+0

Przepraszam, tęskniłem za tą częścią. W takim przypadku myślę, że potrzebujesz wzoru fabrycznego. –

4

Podgląd MEF 8 ma eksperymentalne wsparcie dla tego, chociaż nie jest jeszcze zawarty w System.ComponentModel.Composition.dll. Aby uzyskać więcej informacji, patrz this blog post.

Będziesz musiał pobrać źródła MEF i zbudować rozwiązanie. W folderze Samples\DynamicInstantiation znajdziesz zestaw Microsoft.ComponentModel.Composition.DynamicInstantiation.dll. Dodaj odwołanie do tego zestawu i dodać dynamiczny dostawcy instancji do kontenera tak:

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

Teraz twoje części będą mogli importować PartCreator<Foo> jeśli trzeba dynamicznie tworzyć Foo części. Przewagą nad pisaniem własnej klasy fabryki jest to, że będzie ona w przejrzysty sposób dbać o przywóz Foo i importu importu, itp.

edit:

  • w MEF Preview 9PartCreator został przemianowany na ExportFactory ale jest włączone tylko w wersji Silverlight.
  • w MEF 2 Preview 2, ExportFactory została dołączona do edycji komputerowej. Tak więc ExportFactory będzie prawdopodobnie częścią kolejnej wersji platformy .NET po .NET 4.0.
+0

Dzięki, przejdę do tego linku. – Akash

Powiązane problemy