2013-05-24 17 views
7

È possibile boostrap un sistema di moduli Prism all'interno del servizio WCF? Perché non importa quello che faccio, le mie dipendenze del MEF non vengono soddisfatte.Sistema di moduli prisma dal servizio WCF?

Esempio:

Questo è il mio servizio WCF implementazione

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

Questo è il mio Prism boostrapper di sapore MEF:

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

} 

Ecco il mio moduloche contiene lo interfacce per database del servizio 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 ... 
} 

e, infine, ecco il Prism servizio di database stesso:

[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 ... 
} 

provato questo per le ultime ore senza successo. L'importazione del mio db è sempre null e non viene mai inizializzata.

Nota che tutto funziona se faccio tutto questo senza Prism, ma solo con MEF.

+0

Quindi, per quanto riguarda i progressi su questo problema? –

+0

Penso di aver trovato una soluzione nel libro "Dependency Injection in .NET" (Parte 3, Cap. 7.3). Ancora provandolo. Fondamentalmente si tratta solo di aggancio alla routine di avvio della WCF. – drozzy

+0

Come ho detto nel mio commento. Penso davvero che sia un problema nella configurazione del contenitore e nella registrazione dei tipi ... –

risposta

0

Beh, sembra che la soluzione non è quella di utilizzare Prism a tutti , in quanto non aggiunge nulla di "modulare" con i suoi moduli. Sembra che i moduli siano concetti puramente per applicazioni visive.

Invece, uno deve agganciarsi alla procedura di "avvio" WCF e boostrap il contenitore MEF da lì. La risposta su come farlo è piuttosto complicata (anche se non complicata), poiché WCF ha già molti punti di estensione/hook-in.

La risposta che ho usato si trova nel libro Iniezione di dipendenza in .NET di Mark Seemann nel capitolo 7.3: "Composizione di applicazioni WCF".

In mancanza di copiare l'intero capitolo di quel libro in questa risposta, temo che sia il meglio che posso fare.

1

Non sono sicuro che i seguenti frammenti ti aiuteranno. Ho solo esperienza con PRISM e Unity. Provalo e dimmi cosa sta succedendo.

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

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

Si sta creando e svuotando ModuleCatalog e non lo si configura mai.

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

Non avrete nulla importati nel db campo perché l'oggetto MyService non viene creato dal contenitore - non può essere creato, perché il contenitore è effettivamente creato nel programma di avvio automatico, che è nel costruttore di MyService.

Un modo semplice per risolvere questo è quello di soddisfare le importazioni dell'oggetto dopo l'inizializzazione del contenitore. Per fare ciò, è possibile esporre il contenitore nel programma di avvio automatico in questo modo:

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

    // Rest of bootstrapper definitions... 
} 

quindi modificare s' MyService costruttore:

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

Sì, questo funziona. Grazie. Certo che il fatto è che non avevo nemmeno bisogno di Prism. Stava solo confondendo il problema. Inoltre, la lettura del libro 'Dependency Injection in .NET' ha aiutato a chiarire cosa è stato fatto dove. Soprattutto il loro esempio di come eseguire il bootstrap di WCF. Sono troppo stanco oggi per scrivere la risposta qui, ma quello sarebbe il modo corretto per avviare un servizio WCF. – drozzy

+0

Sì, il Prisma non è probabilmente necessario qui, ma ho pensato che spiegare perché le cose non funzionassero ti avrebbe aiutato a prendere una decisione migliore su come eseguire il bootstrap del tuo servizio permettendoti anche di mantenere la tua attuale implementazione. Ad ogni modo, spero che la mia risposta sia stata di aiuto. –