2010-01-29 11 views
33

Ich verwende den Unity IoC-Container zum Auflösen meiner Objekte. Ich bin jedoch auf ein Problem gestoßen. Wenn ich mehr als einen Konstruktor habe - woher weiß Unity, welchen er verwenden soll? Es scheint den mit Parametern zu verwenden, wenn ich einen mit und einen ohne habe. Kann ich ihm explizit sagen, welcher Konstruktor verwendet werden soll?Angeben des Konstruktors für den zu verwendenden Unity-IoC-Container

Speziell hatte ich einen Fall ähnlich der folgenden Person Klasse mit zwei Konstruktoren. In diesem Fall möchte ich, dass der IoC-Container den Standardkonstruktor verwendet - ohne Parameter -, aber er wählt denjenigen mit Parametern.

Dies schlägt offensichtlich fehl, da das SomeValueObject nicht erstellt werden kann - ohne zu wissen, was in den String-Parameter injiziert werden soll. Der Fehler gibt es:

Auflösung der Abhängigkeit fehlgeschlagen, Type = "MyApp.Person", name = "". Ausnahmebedingungsnachricht lautet: Die aktuelle Buildoperation (Buildschlüssel Buildschlüssel [MyApp.Person, null]) ist fehlgeschlagen: Der Parameter obj konnte nicht aufgelöst werden, wenn versucht wird, den Konstruktor MyApp.Person (MyApp.SomeValueObject obj) aufzurufen. (Strategietyp BuildPlanStrategy, Index 3)

Der Behälter Anmeldung:

Container.RegisterType<Person, Person>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager()); 

Und die Lösung:

var person = Container.Resolve<Person>(); 
+0

Ist nicht der Punkt von IoC, Interfaces zu verwenden ??? – Martin

+3

Sicher, und das mache ich meistens. Aber das machte für die Frage keinen Unterschied. – stiank81

+0

@Martin Viele Programmierer verwenden Klassen und vermeiden die falsche Allgemeingültigkeit, eine Schnittstelle zu erstellen und dann nur eine Implementierung davon zu haben. Es vermeidet auch die Menge an stinkendem IoC-Kabel, die Sie in den meisten Unternehmensanwendungen sehen, lässt aber dennoch einige Implementierungen bei Bedarf abschalten. http://programmers.stackexchange.com/questions/133471/writing-testable-code-vs-avoiding-speculative-generality –

Antwort

46

Registrieren Sie wie diese statt:

container.RegisterType<Person>(new InjectionConstructor()); 

Sie die LifetimeManager hinzufügen können auch eine Überlastung der RegisterType Methode.

Das gesagt, wenn Sie für DI modellieren, wird Ihr Leben viel einfacher sein, wenn Sie eindeutige Konstruktoren haben (d. H. Keine überladenen Konstruktoren).

+0

Welche Überladung referenzieren Sie? – Casey

+0

@Casey ... Ich glaube der leere Konstruktor. – granadaCoder

+0

Da es für InjectionConstructor keine Argumente gibt, ruft es den leeren Konstruktor von Person auf. Wäre der Code 'new InjectionConstructor (new SomeValueObject ("John Smith"))' gewesen, hätte das den (anderen) Person-Konstruktor aufgerufen, wobei der "andere" -Konstruktor derjenige ist, der das SomeValueObject-Objekt/-Argument verwendet. – granadaCoder

4

Multiple-Constructor Injection Using an Attribute

Wenn eine Zielklasse enthält mehr als ein Konstrukteur w ith der gleichen Anzahl von Parametern müssen Sie das InjectionConstructor Attribut zum Konstruktor gelten, dass der Behälter Unity zeigt an verwenden, um den Konstruktor sollte der Behälter verwenden. Wie bei automatische Konstruktor Injektion Sie kann der Konstruktor angeben als konkrete Typ Parameter, oder Sie können eine Schnittstelle oder Basisklasse angeben, für die die Einheit Behälter eine registriert Mapping enthält.

22

Standardmäßig wählt Unity einen Konstruktor mit der maximalen Anzahl von Argumenten. Um dies zu überschreiben, dekorieren Sie den erforderlichen Konstruktor mit InjectionConstructorAttribute.

+4

Wir sollten erwähnen, dass die Dekoration des Konstruktors die Komponente als IoC-Container an Unity koppelt. Es ist wahrscheinlich vorzuziehen, die Spezifikation während der Registrierung zu behandeln, so dass Komponenten keinen Bezug zu Unity nehmen müssen und daher ein anderer IoC bei Bedarf ausgetauscht werden könnte. –

0

Ich muss wirklich darauf hinweisen, wie Sie die Abhängigkeitsinjektion in diesem Fall verwenden, ist einfach falsch. Der Container sollte SomeValueObject in die Konstruktion einfügen können.

Was Sie wahrscheinlich tun sollten, ist ein Standardobjekt von SomeValueObject zu registrieren, dass die.Die Namenseigenschaft gibt stattdessen string.Empty zurück.

+0

Vielleicht ist mein einfaches Beispiel ein bisschen aus, aber imo gibt es einen Bedarf von zwei verschiedenen Konstruktoren im eigentlichen Code .. Danke für die Erwähnung sowieso. – stiank81

+0

Was, wenn Sie es nicht geschrieben haben? – Casey

Verwandte Themen