2009-01-27 9 views
9

Ich versuche, einen IOC-Container zu verwenden, um das anfängliche Objektdiagramm in meiner Anwendung zu erstellen.Umgang mit zirkulären Abhängigkeiten in IOC

Ich habe eine MainForm. Dieses Formular hängt von einem MenuStrip ab, der von mehreren MenuStripItems abhängig ist. Einige MenuStripItems hängen von der MainForm ab.

Im Moment habe ich alle Abhängigkeiten für die Konstruktorinjektion eingerichtet. Offensichtlich führt das Auflösen der MainForm jetzt zu einem Stapelüberlauf, da die MenuStripItem-Abhängigkeiten der MainForm versuchen, das Mainform usw. zu lösen.

Was ist der beste Weg, um diese zirkuläre Abhängigkeit zu lösen?

+1

Ich bin gespannt, wie Sie die Zirkelreferenz behandelt haben, bevor Sie den IOC-Container beteiligt waren ... Haben Sie einen Komponententest, der das Formular alle seine Abhängigkeiten übergibt? – JasonTrue

+0

Vor der Verwendung von IOC, meine MainForm wäre global zugänglich mit einem Singleton. –

Antwort

5

Circular Abhängigkeiten sind ein Zeichen für schlechtes Design, egal ob Sie IoC verwenden oder nicht. Ich schlage vor, dass Sie ein Redesign durchführen, um es zu vermeiden. Das Hinzufügen eines Hilfsobjekts kann eine Lösung sein.

Zum Beispiel machen Sie die MenuStripItems nur von einem Teil der MainForm abhängig, der für sie notwendig ist und nicht im Ganzen.

3

Stellen Sie eine Controller-Klasse her, die die Daten und die Logik bereitstellt, die MainForm und MenuStripItem beide benötigen, um den Zirkelverweis zu vermeiden.

3

Sie können einen Setter zum Injizieren einiger der Abhängigkeiten nach der Konstruktion verwenden.

1

Ich sehe nicht, wie das Erstellen einer Hilfsklasse oder eines Controllers das zirkuläre Abhängigkeitsproblem löst.

Ich werde einige weitere Details geben. Die MenuStripItems hängen von MainForm ab, da sie den Inhalt der MainForm festlegen können. Befolgen Sie die obigen Vorschläge, lassen Sie uns sagen, dass ich eine separate Schnittstelle für den MainForm-Inhalt, IFormContent, erstelle. MenuStripItem kann dann von IFormContent abhängen. Aber eine Implementierung von IFormContent wird dann wiederum von MainForm abhängen, was zu einer zirkulären Abhängigkeit führt.

Vielleicht sollte ich Setter Injektion irgendwo statt Konstruktor Injektion greifen?

+1

Sie haben eine Controller-Klasse mit einer Eigenschaft: Inhalt. MenuStripItem legt die Content-Eigenschaft auf dem Controller fest, und MainForm liest sie. Diese beiden Klassen verweisen also auf den Controller, aber der Controller weiß nichts über die beiden GUI-Klassen. Also kein Zirkelbezug. –

0

Wie werden MenuStrip und MenuStripItems erstellt?

Wenn ich IOC verwendet habe, gibt es immer eine 1: 1-Beziehung zwischen einem Dienst und den Abhängigkeiten, die der IOC-Container für den Dienst bereitstellt. Wenn ein Service mehr als einen von etwas benötigt, hat er eine 1: 1-Beziehung mit einem einzelnen Factory-Objekt, das die mehreren Elemente erstellt. Diese Factory-Methode kann so parametrisiert werden, dass die erstellten Objekte auf ihren Container verweisen können.

3

Ich stimme mit kgiannakakis:

Zirkuläre Abhängigkeiten sind ein Zeichen für schlechtes Design, egal ob Sie IoC verwenden oder nicht. Ich schlage vor, dass Sie ein Redesign tun, um es zu vermeiden. Hinzufügen eines Helfers Objekt kann eine Lösung sein.

Um herauszufinden, welche Methoden in die Hilfsklasse extrahiert werden sollen, kann dieser Prozess helfen:

Da Sie eine Klasse A und eine Klasse B, die sich auf einander und eine zirkuläre Abhängigkeit schaffen. Um herauszufinden, welche Methoden in ein externes Helper-Objekt extrahiert werden sollen, listen Sie alle von Klasse A verwendeten Methoden in Ihrer Klasse A und alle Methoden in Klasse B auf, die von Klasse A verwendet werden. Die kürzere der beiden Listen ist ausgeblendet Hilfsklasse C.

Inspiriert von Miško Hevery http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

1

Sie benötigen einen Händler Klasse (oder Schnittstelle) mit Bezug beiden Klassen erstellen Sie sie verwenden. Sie sollten diesen Händler Klasse (oder Schnittstelle) lieber als jede Referenzklassen verwenden, die Sie zuvor verwendet haben.

Erklärung der Lösung:
Betrachten 3 Klassen wie folgt:

public Class A { 
    public Method CommonMethod(){ 
     //Some implementation... 
    } 

    Method C(){ 
     //CommonMethod form class B are using here 
     B obj = new B(); 
     B.CommonMethod(); 
    } 
} 


public Class B { 
    public Method CommonMethod(){ 
     //Some implementation... 
    } 

    Method D(){ 
     //CommonMethod form class A are using here 
     A obj = new A(); 
     A.CommonMethod(); 
    } 
} 


public Class DealerClass { 
    private readonly A _inctanceA; 
    private readonly B _inctanceB; 

    //Cunstructor method of the class 
    DealerClass(A inctanceA, B inctanceB){ 
     _inctanceA = inctanceA; 
     _inctanceB = inctanceB; 
    } 

    //Using CommonMethod of class A 
    public UsingCommonMethodA(){ 
     _inctanceA.CommonMethod(); 
    } 

    //Using CommonMethod of class B 
    public UsingCommonMethodB(){ 
     _inctanceB.CommonMethod(); 
    }  
} 

So nach dieser Lösung sollten Sie Methoden anderer Klassen verwenden, die miteinander zirkuläre Abhängigkeit haben in der DealerClass.

+0

scheint es detaillierter. –

Verwandte Themen