IoC mit Werttyp und Objekttypabhängigkeiten

8

Ich bin auf der Suche nach Vorschlägen für die beste Art, Objekte für IoC zu entwerfen

Angenommen, ich habe ein Objekt (Service), das eine Abhängigkeit von einem DataContext hat, der bei Ioc registriert ist.

Aber es erfordert auch eine Namenseigenschaft, ich könnte das Objekt so gestalten:

%Vor%

Das Problem ist, dass es sehr kompliziert wird, mit Ioc-Containern zu verwenden, da ein String-Objekt wie Name nicht einfach zu registrieren ist und die Verwendung mit dem Ioc-Container kompliziert wird: So wird die Auflösung verwirrend:

%Vor%

Ein anderer Ansatz ist, es wie folgt zu gestalten:

%Vor%

Die Auflösung ist jetzt einfacher:

%Vor%

Die einzige Einschränkung ist, dass der Name nicht mehr benötigt wird. Ich würde gerne von DI- oder IoC-Experten hören, wie sie das machen würden und trotzdem der Beton-IOC-Behältertechnologie ziemlich agnostisch gegenüberstehen.

Ich weiß, dass vieles davon abhängt, wie Sie das verwenden möchten, Option 2 wäre perfekt, wenn der Name wirklich optional wäre. Aber in dem Fall, in dem der Name erforderlich ist, könnten Sie den Validierungsschritt an einem anderen Punkt im Code hinzufügen, sondern stattdessen den Entwurf verwenden, um Ioc einfacher zu machen.

Gedanken?

    
Andre 14.11.2011, 16:23
quelle

5 Antworten

4

Ihre Wahl des DI-Containers sollte nicht das Design Ihrer API diktieren. Wenn name nicht optional ist, sollte es Teil der Signatur des Konstruktors sein (also zwingend erforderlich).

Die nächste Frage wird dann sein, wie man den Container ohne hohen Aufwand konfigurieren kann. Wie das geht, hängt vom Container ab. So implementieren Sie eine Konvention um ein String-Argument in Castle Windsor:

%Vor%

Dann registrieren Sie die NameConvention mit dem Container wie folgt:

%Vor%

Wenn Ihr Container nicht über die entsprechenden Erweiterungspunkte verfügt, wählen Sie einen entsprechenden Container aus.

    
Mark Seemann 14.11.2011, 17:36
quelle
3
  

Das Problem ist, dass die Verwendung mit Ioc-Containern sehr kompliziert wird   als String-Objekt wie Name ist nicht einfach zu registrieren und die Verwendung   wird mit dem Ioc-Container

kompliziert

Die meisten guten IoC-Container bieten einfache Möglichkeiten, Konstruktorargumente bei der Konfiguration anzugeben.

Ihre erste Beispiel-Konstruktor-Injektion wird normalerweise als der bevorzugte Weg betrachtet. Stellen Sie sich Ihren Konstruktor als einen zu befolgenden Vertrag vor, der nach der Erfüllung ein gültiges Objekt rendert.

Ihre zweite Codemustereigenschaftsinjektion wird normalerweise als weniger vorteilhaft für die Konstruktorinjektion angesehen. Wie auch immer, IoC-Container geben Ihnen normalerweise die Möglichkeit, Werte für Konstruktorparameter oder Eigenschaften bei der Konfiguration anzugeben, die jedes Mal bereitgestellt werden, wenn Sie Ihren IoC um die Erstellung dieses Objekts bitten.

Ich bin mir nicht sicher, welchen IoC-Container Sie verwenden möchten, aber hier ist ein Beispielcode, mit dem Sie StructureMap konfigurieren und String-Werte für verschiedene Dienste bereitstellen können. Wenn ich Ihre Frage nicht falsch interpretiere, scheint dies das zu sein, was Sie anstreben.

%Vor%

BEARBEITEN

Beantworten Sie den Kommentar, wenn Sie ein Konstruktorargument manuell liefern wollten, würde es so aussehen:

%Vor%

Offensichtlich kann dies schnell hässlich werden, also sollten Sie einige Fabrik- / Hilfsmethoden auffrischen, wenn Sie sich häufig dabei befinden.

    
Adam Rackis 14.11.2011 16:27
quelle
2

Der Ansatz, den ich normalerweise in einer solchen Situation mache, besteht darin, ein Einstellungsobjekt anstelle eines Strings zu injizieren und dann im Konstruktor nach der Eigenschaft zu fragen, die diese Zeichenfolge darstellt. Oder in einigen Fällen noch besser, wenn ich diese String-Eigenschaft brauche, habe ich sie aus diesen Einstellungen herausgenommen, damit sie geändert werden kann (nützlich, wenn es sich wirklich um eine Programmeinstellung handelt).

Die andere Option besteht darin, eine bindende Annotation zu verwenden. Ich weiß nicht, welches Abhängigkeits-Injection-Framework Sie verwenden, aber hier ist, wie es in guice (Java) Framework, mit dem ich gerade arbeite.

    
0lukasz0 14.11.2011 16:45
quelle
1

Wenn Sie Castle Windsor verwenden, können Sie typisierte Fabriken verwenden, die Sie über hier . Im Wesentlichen ermöglichen typisierte Factories das Erstellen einer Schnittstelle, die so aussieht.

%Vor%

Wenn Sie dies einfügen und Create() mit dem Namen Ihrer Wahl aufrufen, gibt Windsor eine konstruierte IService -Implementierung zurück.

    
gcso 14.11.2011 16:39
quelle
1

Entwerfen Sie es so, wie Sie es immer tun würden, wobei Sie gute technische Praktiken berücksichtigen (SOLID usw.). Dann, wenn Ihr Container Ihrer Wahl Sie einschränkt, verwenden Sie ihn entweder nicht richtig oder Sie verwenden einen falschen Container.

Im Fall Windsor können Sie bei der Registrierung einfach inline fest codierte Abhängigkeiten zu Komponenten bereitstellen:

%Vor%

Sie können auch dynamischere Abhängigkeiten bereitstellen oder von Werten aus Ihrer XML-Konfiguration abhängig sein, wenn Sie diese nach der Kompilierung ändern müssen.

Wenn der Wert optional ist, machen Sie ihn optional, indem Sie entweder einen Konstruktor verwenden, der einen Standardwert für ihn angibt, indem Sie Überladungen des Konstruktors verwenden oder als Eigenschaft. Auch hier wird ein guter Container alle diese Fälle behandeln, wenn der, den Sie gerade verwenden, nicht zu einem besseren wechselt.

    
Krzysztof Kozmic 14.11.2011 21:47
quelle