2012-05-30 10 views
6

In meiner Prism-App ist der MEF-Container innerhalb der Bootstrapper-Klasse über die Container-Eigenschaft verfügbar.Warum MEF-Container ist nicht in Modulen verfügbar?

Aber es ist nicht aus dem Klassenmodul (IModule). Ich kann den Container nur über IServiceLocator importieren.

Warum? Ich dachte, dass es sinnvoll ist, eine gemeinsame Schnittstelle gegen Betontechnologie zu verwenden, aber die Prism 4.1 Richtlinie fordert uns auf, IServiceLocator nicht zu verwenden (in Considerations for Using IServiceLocator).

Antwort

6

Ich denke, es entspricht nicht Prism oder MEF, aber zu Dependency Injection Prinzip und Best Practices im Allgemeinen. (Ja, ich knote, dass MEF kein DI-Container ist, aber hier wird es fast als DI-Container verwendet, also nehme ich hier die gleichen Praktiken an).

In Best Practices von DI (this Buch ist sehr cool, ich kann es nur empfehlen) es ist gut, solche Schritte in DI "Workflow" zu haben:

  • Register alle erforderlichen Typen (in Prism - von Bootstrapper. ConfigureCatalog() -Methode)
  • resolve Wurzelobjekt (mit allen verschachtelten Objekten In Prism -. durch Bootstrapper.CreateShell() -Methode)
  • verwenden Ihr Wurzelobjekt
  • Release Ihnen Wurzelobjekt

Idealerweise sollten Sie den DI-Container NICHT mehr verwenden. Ihr Code sollte NICHT wissen, dass der DI-Container existiert (von dieser Seite aus ist Unity wirklich ein DI-Container, weil Sie Code schreiben können, der nichts über die Verwendung eines DI-Containers weiß). Wenn Ihr Code davon weiß - es hängt sich vom DI-Container ab, und das ist schlecht.

PS.Wenn Sie ohnehin MEF Container in Ihrem Modul verwendet werden sollen (zum Beispiel, weil Sie mit DI Paradigma nicht sehr vertraut sind, oder Sie haben einige sehr spezifische Aufgaben), können Sie so etwas wie versuchen:

[ModuleExport(typeof(YourModule))] 
public class YourModule : IModule 
{ 
    public static CompositionContainer CompositionContainer; 

    [ImportingConstructor] 
    public void YourModule(CompositionContainer container) 
    { 
     this.CompositionContainer = container; 
    } 
} 

Do not Vergessen Sie nicht, Ihren MEF-Container selbst in Ihrem Boostrapper zu registrieren:

+1

Während ich mit den Best Practices übereinstimme, wird in der Prism-Dokumentation eindeutig angegeben, dass Sie auch die Initialize-Methode Ihrer Methode verwenden können, um "Shared Services mit dem Abhängigkeitsinjektionscontainer der Anwendung zu registrieren". http://msdn.microsoft.com/en-us/library/gg405479%28v=pandp.40%29.aspx – Console

+2

Wenn wir nicht über den Container wissen sollen, wie können dann Module neue Shared Services registrieren? – Benjamin

+0

Der erwähnte 'ComposeExportedValue' ist eine Erweiterungs-Methode in' System.ComponentModel.Composition.AttributedModelServices' – jan

0

Beachten Sie, dass ich eine ältere Version von Prism verwende und dass ich es mit dem UnityContainer verwende, aber dass dieselben Prinzipien gelten sollten.

Definieren Sie Ihre Modulklasse, um einen Container im Konstruktor zu übernehmen.

Hier ist ein Beispiel mit Unity:

public class Module : IModule 
{ 
    public static IUnityContainer Container; 

    public Module(IUnityContainer container) 
    { 
     Container = container; 
    } 
} 

Wenn Sie einen Konstruktor definieren, die einen Behälter nimmt, wird es durch die ApplicationBootstrapper.Run() -Methode aufgerufen.

Ich testete mit einem Standard-Konstruktor ohne Parameter und einem Überladungskonstruktor, der den Container übernimmt und der zweite Konstruktor aufgerufen wurde.

Ich überprüft auch mit nur den Standardkonstruktor und es wurde aufgerufen. Ich würde vorschlagen, Sie ändern Ihren Konstruktor, um einen Parameter hinzuzufügen, der einen Behälter nimmt.

Wenn Sie einen Container in Ihrer Modulklasse haben, können Sie Typen in Ihrer Initialize-Methode registrieren.

Wie für ServiceLocator, das ist ein etwas anderes Muster, das ich Ihnen empfehlen würde in Fällen verwenden, in denen Sie Ihre Abhängigkeiten nicht aus irgendeinem Grund vom Container erstellt werden können.

+0

Ich habe versucht, das zu tun. MEF verwendet den CompositionContainer-Typ anstelle von Unity's IUnityContainer. Aber mein Konstruktor mit dem Parameter typed CompositionContainer wird nicht ausgeführt. –

+0

@reito: Haben Sie auch einen Standardkonstruktor und wie rufen Sie die ApplicationBootstrapper run-Methode auf? – Gilles

+0

Ich habe keine Konstrukteure mehr, nur diese. Die Bootstrapper-Methode Run ruft die OnStartup-Methode meiner Application-Klasse auf. –

Verwandte Themen