2016-09-28 1 views
0

Ich versuche, IOC/DI-Container zu verwenden, aber wenn Sie ein Kind-Fenster erstellen, was ist die beste Praxis?IOC/DI-Container und Kind Fenster Erstellung Dilemma

Wo ich habe Dilemma ist:

public class ParentWindow : Form 
{ 
    public void OpenChildWindow() 
    { 
     var child = IocContainer.Instance.Resolve<ChildWindow>(); // big issue !!! an-ti server locator pattern 
     child.Show(); 
    } 
} 

Oder

public class ParentWindow : Form 
    { 

      private Container _container 

      public ParentWindow(Container container) // no, no, you have dependence on container 
      { 
      } 

     public void OpenChildWindow() 
     { 
      var child = _container.Resolve<ChildWindow>(); 
      child.Show(); 
     } 
    } 

Meine Lösung

public class ParentWindow : Form 
{ 
    private IFormFactory _factory 

    public ParentWindow(IFormFactory factory) // inject from IOC container 
    { 
    } 

    public void OpenChildWindow() 
    { 
     var child = _factory.CreateChildWindow(); 
     child.Show(); 
    } 
} 

Aber mit meiner Lösung, meine Fabrik Art meiner eigenen IOC-Container werden, Alle meine elterlichen Fenster müssen in einer Fabrik passieren, ist das nicht meine Fabrik wird der neue "Server Locator".

Gibt es eine andere bessere Lösung dafür?

+0

Verwandte: https://stackoverflow.com/questions/38417654/winforms-how-to-register-forms-with-ioc-container/38421425#38421425 – Steven

+0

@ Steven nicht mein Problem lösen – LeY

Antwort

0

Die Verwendung von DI bedeutet, dass Sie den Container als Service Locator verwenden, vorzugsweise in einer einzelnen Codezeile, die genau einmal ausgeführt wird. Dies wird als "Composition Root" bezeichnet, wo der Container konfiguriert und der Stamm des Objektdiagramms erstellt wird.

In diesem Sinne verstößt der oberste Code in Ihrem Beispiel nicht gegen dieses Prinzip.

Nebenbei bemerkt:

Was ich immer tun, ist es, den Container Framework-Code mit meiner eigenen Klasse wickeln, so dass ich wechseln DI mehr Frameworks es easily- zu betrachten.

+0

die DI doesn Verwendung Ich nehme nicht an, den Container direkt zu verbrauchen. Es könnte sogar als ein Code-Geruch betrachtet werden, um die Abhängigkeit über den gesamten Stapel hinweg explizit zu haben. Mit einer Kombination aus dem Kompositionswurzel und der lokalen Factory können Sie nur den oberen Teil des Stapels von dem Container abhängig machen und lokale Fabriken überall verwenden, ohne Abhängigkeit von irgendwelchen Containern. –

+0

stimme ich vollständig zu, und das ist genau das, was ich sagte - wenn Sie aufmerksam lesen - abzüglich der lokalen Fabriken Teil, die ich nicht erwähnt habe. (Bearbeiten Sie die Antwort, so dass es klarer wäre). @ WiktorZychla –

+0

Beachten Sie, dass die CR nur die Hälfte der Geschichte ist. Sie können den Container dort konfigurieren, aber Sie müssen den Container irgendwie den Stapel weiterleiten. Die Idee der lokalen Fabriken ist die andere Hälfte. Mit lokalen Fabriken entfällt die Notwendigkeit, auf den Container zu verweisen. –

1

Die von Ihnen vorgeschlagene Lösung ist ein großer Schritt in die richtige Richtung. Die Fabrik riecht nicht wirklich nach einem Lokator, sondern nach einer lokalen Fabrik, die Teil der Domäne ist, zu der sie gehört. Ein Schritt noch weiter wäre es, die Idee der Familie der Fabriken (die Schnittstelle) zu vergessen und eine konkrete Fabrik mit steckbarer Implementierung zu haben, die intern einen Container benutzt (oder keinen benutzt), aber eine einzige API für ihren anbietet Kunden. Auf diese Weise können Sie die Konstruktorinjektion der Fabrik in das Formular entfernen, indem Sie einfach den Betontyp der Fabrik verwenden. Die Factory selbst ist im Kompositionswurzel konfiguriert.

Mehr Details und Code-Beispiel in meinem Blog-Eintrag

http://www.wiktorzychla.com/2016/01/di-factories-and-composition-root.html

0

Erstes Beispiel: Ich mag es nicht, weil Sie auch Abhängigkeiten haben, die man nicht Unit-Test. Es wird Instanz von ChildWindow auflösen, und Sie können es nicht steuern (vortäuschen).

Zweites Beispiel: Ich mag nicht, weil Sie Klasse Container nicht Schnittstelle verwenden.

Drittes Beispiel: Es funktioniert besser als früher und manchmal verwende ich Fabrik auf diesem Weg. Es kann vollständig getestet werden.

Normalerweise denke ich, dass es besser ist, DI-Container als Fabrik zu verwenden, weil es mehr Funktionalitäten wie z.B. Objektlebensdauer ...

Ich habe nie Klasse ChildWindow verwendet, aber wenn ich nicht in der Konstruktorschnittstelle definieren kann, werde ich eher einige ChildWindowWrapper implementieren: IChildWindowWrapper und diesen Wrapper verwenden. Es vereinfacht die Gerätetests und kann aus DI-Containern verwendet werden.

+0

können Sie einige Beispiele für "verwenden DI-Container als Fabrik" und "ChildWindowWrapper" – LeY

+0

@LeY Sorry, wenn Ton zweideutig. Ich möchte sagen, dass ich lieber den DI-Container für die Erstellung neuer Instanzen von Objekten verwenden werde, anstatt das Factory-Muster (Methode) zu verwenden. Wenn beispielsweise die Klasse Interface oder Abstract-Klasse nicht implementiert, verwende ich Wrapper-Klasse. Wrapper ist eine Klasse, die bestimmte Funktionalitäten kapselt, die Sie benötigen. Anstatt direkt in Ihrem Code Code zu verwenden, müssen Sie Wrapper direkt verwenden. Wrapper muss die Schnittstelle implementieren und Sie können sich mit Ihrem DI-Container registrieren. – kat1330