2010-09-15 3 views
9

Ich versuche, eine Abhängigkeit zu meinen MVC-Controller wie dieseUnity-Framework IoC mit Standardkonstruktors

private static void RegisterContainer(IUnityContainer container) 
{    
    container 
     .RegisterType<IUserService, UserService>() 
     .RegisterType<IFacebookService, FacebookService>(); 
} 

Die Userservice-Klasse einen Konstruktor wie dies hat zu injizieren ...

public UserService(): this(new UserRepository(), new FacebookService()) 
{ 
    //this a parameterless constructor... why doesnt it get picked up by unity? 
} 

public UserService(IUserRepository repository, IFacebookService facebook_service) 
{ 
    Repository=repository; 
    this.FacebookService=facebook_service; 
} 

Die Ausnahme ich erhalte die folgende ...

Stromart, Repositories.IUserRepository, ist eine Schnittstelle und kann nicht konstruiert werden. Vermissen Sie einen Typ Zuordnung?

Es sieht so aus, als würde versucht, einen Konstruktor in den Dienst zu injizieren, aber der Standard würde ausreichen? Warum wird dem parameterlosen Konstruktor nicht zugeordnet?

+0

Was sind 'Repository' und' this.FacebookService'? – SwDevMan81

Antwort

25

The Unity Standardkonvention (das ist ziemlich klar geschrieben ist in der Dokumentation aus) ist der Konstruktor mit den meisten Parametern zu wählen. Sie können nicht einfach eine pauschale Aussage machen, dass "es nicht wahr ist, dass IoC den spezifischsten Konstruktor findet. Wenn Sie die Konstruktorparameter bei der Registrierung eines Typs nicht angeben, wird automatisch der Standardkonstruktor aufgerufen." Jede Containerimplementierung kann und hat unterschiedliche Standardeinstellungen.

In Unity Fall, wie ich schon sagte, wird es den Konstruktor mit den meisten Parametern wählen. Wenn es zwei gibt, die die meisten Parameter haben, dann wird es mehrdeutig sein und werfen. Wenn Sie etwas anderes möchten, müssen Sie den Container dafür konfigurieren.

Zur Auswahl stehen:

das Setzen [InjectionConstructor] Attribut auf den Konstruktor Sie angerufen werden soll (nicht empfohlen, aber schnell und einfach).

Verwendung der API:

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

Verwenden von XML-config:

<container> 
    <register type="UserService"> 
    <constructor /> 
    </register> 
</container> 
+0

Schade, dass selbst das veraltete Windsor Castle den besten übereinstimmenden Konstrukteur auswählt und Unity immer noch nicht kann. –

+0

Es war ein bewusster Kompromiss. Unity kann konkrete Typen auflösen, die nicht mit dem Container registriert sind, Windsor kann das nicht wissen. Dies macht "am besten übereinstimmend" wirklich mehrdeutig, also gingen wir mit einem deterministischeren Standard. –

+1

Danke für die Klarstellung. Ich sehe, mein Kommentar enthält unnötige starke Argumente. Das sollte sein "Einheit wählt nicht Konstruktor automatisch aus" anstelle von "kann nicht" :) Sieht so aus, als ob sie einen anderen Weg nach Designentscheidung gewählt hätten. Http://Stackoverflow.com/a/499675/929902 Wie auch immer, ich bin glücklich mit Unity und mit es ist Flexibilität. –

0

Ich kann nicht speziell mit Unity sprechen, aber IoC-Container werden im Allgemeinen versuchen, den spezifischsten Konstruktor zu verwenden, den sie finden können , weil es ein Konstruktor ist.

Wenn es einen Konstruktor gibt, der zwei Abhängigkeiten für die Injektion benötigt, dann sind sie vermutlich für die Verwendung des Objekts erforderlich; Der Standardkonstruktor muss etwas tun, um sie zu erfüllen, wenn der Container ihn aufruft. Die Aufgabe des Containers besteht darin, Abhängigkeiten zu erfüllen, also warum sollte es der Klasse überlassen werden, dies zu tun, wenn es nicht angewiesen würde, es der Klasse zu überlassen?

Um Ihre konkrete Frage, nach Ihrem Code:

private static void RegisterContainer(IUnityContainer container) 
{    
    container 
     .RegisterType<IUserService, UserService>() 
     .RegisterType<IFacebookService, FacebookService>(); 
} 

IUserRepository ist nicht registriert. Fügen Sie eine Zeile wie

.RegisterType<IUserRepository, UserRepository>() 
+0

Es ist nicht wahr, dass IoC den spezifischsten Konstruktor findet. Wenn Sie beim Registrieren eines Typs die Konstruktorparameter nicht angeben, wird automatisch der Standardkonstruktor aufgerufen. – TalentTuner

+0

Ich weiß nicht, welche Container Sie verwendet haben, aber fast nie Konstruktoren in meinen Mappings. Ich weiß sicher, dass StructureMap dem Standardkonstruktor einen erfüllenderen Konstruktor vorzieht - ich verwende es in meinem aktuellen Projekt und teste so einige der Objekte, die einen Standardkonstruktor haben müssen (zum Beispiel WCF Services)). Ich bin mir ziemlich sicher, dass Castle Windsor auch einen spezifischeren Konstrukteur bevorzugen wird. – arootbeer

+1

@saurabh In meiner Erfahrung mit Unity wird, wenn keine Parameter angegeben sind, der spezifischste Konstruktor verwendet. –