2013-05-24 16 views
7

Czy możesz wzmocnić system modułów Prism z poziomu usługi WCF? Ponieważ nie ważne, co robię, moje zależności MEF nie są spełnione.System modułów pryzmatycznych z usługi WCF?

Np

To mój usługa WCF realizacja

public class MyService : IMyServiceContract{ 
    // This should get filled by MEF after Prism loads the required modules 
    [Import] 
    IDatabase db; 

    public MyService(){ 
     var bootsrapper = new MyServiceBoostrapper(); 
     bootsrapper.Run(); 
    } 
} 

To mój Prism boostrapper z MEF Smak:

public class MyServiceBoostrapper : MefBootstrapper 
{ 
    protected override void ConfigureContainer() 
    { 
     base.ConfigureContainer(); 
    } 

    protected override IModuleCatalog CreateModuleCatalog() 
    { 
     return new ConfigurationModuleCatalog(); 
    } 
    protected override void ConfigureAggregateCatalog() 
    { 
     base.ConfigureAggregateCatalog(); 

     // TODO: Add this assembly ... don't know why 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(MyServiceBoostrapper).Assembly)); 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(IDatabase).Assembly)); 
     // This is what provides the service 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(DatabaseImpl).Assembly)); 
    } 

    protected override DependencyObject CreateShell() 
    { 
     // we don't need the shell 
     return null; 
    } 

} 

Oto moja moduł że zawiera interfejsy do bazy danych serwisu Prism:

[ModuleExport(typeof(IDatabase))] 
public class ModuleActivator : IModule 
{ 
    public void Initialize() 
    { 
     // Do nothing as this module simply provides the API. 
    } 
} 
public interface IDatabase 
{ 
    // interface methods here ... 
} 

i wreszcie jest tu Prism usługi bazy danych sama:

[ModuleExport(typeof(DatabaseImpl), DependsOnModuleNames = new string[] { "IDatabase" })] 
public class ModuleActivator : IModule 
{ 
    public void Initialize() 
    { 
     // Do nothing as this is a library module. 
    } 
} 

[Export(typeof(IDatabase))] 
public class DatabaseImpl : IDatabase 
{ 
    /// implementation here ... 
} 

próbował tego w ciągu ostatnich kilku godzin bez powodzenia. Mój import db jest zawsze null i nigdy nie jest inicjowany.

Zauważ, że wszystko działa, jeśli robię to wszystko bez Prism, ale tylko z MEF.

+0

A co z postępami w tej sprawie? –

+0

Myślę, że znalazłem rozwiązanie w książce "Dependency Injection in .NET" (część 3, rozdział 7.3). Wciąż testuję to. Zasadniczo jest to tylko kwestia podpięcia się do rutyny uruchamiania WCF. – drozzy

+0

Tak jak powiedziałem w swoim komentarzu. Naprawdę uważam, że jest to problem z konfigurowaniem kontenera i aktualizowaniem typów ... –

Odpowiedz

0

Cóż, wydaje się, że rozwiązanie nie jest w użyciu pryzmat w ogóle , ponieważ nie dodaje nic "modułowego" do swoich modułów. Wygląda na to, że moduły są koncepcjami czysto wizualnymi.

Zamiast tego należy przechwycić procedurę "uruchamiania" WCF i pobrać z niej kontener MEF. Odpowiedź na pytanie, jak to zrobić, jest raczej zaangażowana (choć nie jest skomplikowana), ponieważ WCF ma już wiele rozszerzeń/punktów zaczepienia.

Odpowiedź, której użyłem, znajduje się w książce Dependency Injection w .NET autorstwa Mark Seemann w rozdziale 7.3: "Komponowanie aplikacji WCF".

Skopiowanie całego rozdziału z tej książki do tej odpowiedzi, obawiam się, że to najlepsze, co mogę zrobić.

1

Nie jestem pewien, czy poniższe fragmenty ci pomogą. Mam tylko doświadczenie z PRISM i Unity. Po prostu spróbuj i powiedz mi, co się dzieje.

protected override void ConfigureContainer() 
    { 
     base.ConfigureContainer(); 

     this.RegisterTypeIfMissing(typeof(IDatabase), typeof(DatabaseImpl), true); 
    } 

Tworzysz również i opróżniasz ModuleCatalog i nigdy go nie konfigurujesz.

protected override void ConfigureModuleCatalog() 
     { 

      base.ConfigureModuleCatalog(); 

      var moduleCatalog = (ModuleCatalog)ModuleCatalog; 

      Type Initial = typeof(ModuleActivator); 
      moduleCatalog.AddModule(new ModuleInfo 
      { 
       ModuleName = Initial.Name, 
       ModuleType = Initial.AssemblyQualifiedName 
      }); 
     } 
3

Nie mam nic importowane do pola db ponieważ obiekt MyService nie jest tworzony przez pojemnik - nie mogą być tworzone przez nią, bo pojemnik jest rzeczywiście tworzone w inicjującego, który jest w konstruktorze MyService.

Jednym z prostych sposobów rozwiązania tego problemu jest zaspokajanie importu obiektu po zainicjowaniu kontenera. Aby to zrobić, można wystawiać pojemnik w inicjującego tak:

public class MyServiceBoostrapper 
{ 
    public CompositionContainer MyServiceContainer 
    { 
     get { return Container; } 
    } 

    // Rest of bootstrapper definitions... 
} 

Następnie zmodyfikować MyService „s konstruktora:

public MyService() 
{ 
    var bootsrapper = new MyServiceBoostrapper(); 
    bootsrapper.Run(); 

    // This is an extension method. You'll need to add 
    // System.ComponentModel.Composition to your using statements. 
    bootstrapper.MyServiceContainer.SatisfyImportsOnce(this); 

    // At this stage, "db" should not be null. 
} 
+0

Tak, to działa. Dzięki. Oczywiście, nie potrzebowałem nawet Prism. To tylko myliło ten problem. Ponadto przeczytanie książki 'Dependency Injection in .NET' pomogło wyjaśnić, co zostało zrobione gdzie. Zwłaszcza ich przykład jak uruchomić bootstrap WCF. Jestem zbyt zmęczony, aby napisać tę odpowiedź tutaj, ale to byłby właściwy sposób na załadowanie usługi WCF. – drozzy

+0

Tak, Pryzmat prawdopodobnie nie jest tu konieczny, ale pomyślałem, że wyjaśnienie, dlaczego rzeczy nie działały, pomogłoby ci podjąć lepszą decyzję, jak uruchomić usługę, a jednocześnie zachować bieżącą implementację. W każdym razie, miej nadzieję, że moja odpowiedź była jakiejś pomocy. –

Powiązane problemy