2010-09-15 22 views
9

sto cercando di iniettare una dipendenza ai miei controller MVC come questoUnità IoC quadro con predefinito costruttore

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

La classe UserService ha un costruttore come questo ...

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; 
} 

L'eccezione sto ottenendo è la seguente ...

il tipo corrente, Repositories.IUserRepository, è un'interfaccia e non può essere costruita. Ti manca una mappatura del tipo ?

Sembra che stia provando a iniettare un costruttore nel servizio, ma il valore predefinito sarebbe sufficiente? Perché non sta mappando il costruttore senza parametri?

+0

Quali sono '' Repository' e this.FacebookService'? – SwDevMan81

risposta

25

La convenzione Unity di default (che è abbastanza chiaramente indicato nella documentazione) è quello di scegliere il costruttore con il maggior numero di parametri. Non puoi semplicemente fare una dichiarazione generale che "non è vero che IoC troverà il costruttore più specifico, se non specifichi i parametri del costruttore durante la registrazione di un tipo, chiamerà automaticamente il costruttore predefinito". Ogni implementazione del contenitore può avere e ha diversi valori di default.

Nel caso di Unity, come ho detto, sceglierà il costruttore con il maggior numero di parametri. Se ce ne sono due che hanno il maggior numero di parametri, allora sarà ambiguo e gettato. Se vuoi qualcosa di diverso, devi configurare il contenitore per farlo.

Le scelte sono:

Mettere l'attributo [InjectionConstructor] sul costruttore che si desidera chiamato (non raccomandato, ma semplice e veloce).

Utilizzando l'API:

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

Utilizzando configurazione XML:

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

Che peccato, anche il vecchio castello di Windsor sceglie il costruttore più adatto e Unity non può ancora. –

+0

È stato un compromesso deliberato. Unity può risolvere tipi concreti che non sono registrati con il container, Windsor non può che io sappia. Questo rende la "migliore corrispondenza" davvero ambigua, quindi siamo andati con un default più deterministico. –

+1

Grazie per il chiarimento. Vedo che il mio commento contiene argomenti forti non necessari. Questo dovrebbe essere "L'unità non seleziona automaticamente il costruttore" invece di "non può" :) Sembra che abbiano scelto un altro percorso anche in base alla decisione di progettazione http://stackoverflow.com/a/499675/929902 Comunque sono felice con Unity e con è flessibilità. –

0

Non riesco a parlare in modo specifico a Unity, ma i contenitori IoC tenteranno generalmente di utilizzare il costruttore più specifico che possono trovare perché è un costruttore.

Se esiste un costruttore che richiede due dipendenze per l'iniezione, presumibilmente sono necessarie per l'utilizzo dell'oggetto; il costruttore predefinito dovrà fare qualcosa per soddisfarli se il contenitore lo chiama. Il compito del contenitore è di soddisfare le dipendenze, quindi perché dovrebbe lasciare alla classe di farlo se non fosse stato istruito a lasciarlo alla classe?

Per tua domanda specifica, in base al codice:

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

IUserRepository non è registrato. Aggiungere una linea simile a

.RegisterType<IUserRepository, UserRepository>() 
+0

non è vero che IoC troverà il costruttore più specifico, se non si specificano i parametri del costruttore durante la registrazione di un tipo, chiamerà automaticamente il costruttore predefinito. – TalentTuner

+0

Non so quali contenitori hai usato, ma non ho quasi mai specificato costruttori nelle mie mappature. So per certo che StructureMap preferirà un costruttore più soddisfacente al costruttore predefinito - lo sto usando nel mio progetto corrente, ed è così che collaudo unitamente alcuni degli oggetti che devono avere un costruttore predefinito (Servizi WCF, per esempio). Sono abbastanza sicuro che Castle Windsor preferirà anche un costruttore più specifico. – arootbeer

+1

@saurabh Nella mia esperienza con Unity, quando non vengono specificati parametri viene utilizzato il costruttore più specifico. –

Problemi correlati