2009-11-06 26 views
10

Sono nuovo per i contenitori IOC e sto iniziando con NInject.Iniezione del costruttore con altri argomenti del costruttore, non dipendenti

Cosa si fa se si desidera che il costruttore disponga di parametri che non siano servizi e non sia necessario creare un'istanza dal contenitore IOC?

Ad esempio:

public class Person 
{ 
    private readonly string _name; 
    private readonly IPersonRepository _repository; 

    public Person(string name, IPersonRepository repository) 
    { 
     _name = name; 
     _repository = repository; 
    } 

    ...... 
} 

Immaginate che nome è un requisito della classe Person, quindi, al fine di garantire che una persona ha sempre un nome, è necessario che essa sia passata in al costruttore.

Come si ottiene un'istanza di Person utilizzando NInject? Il nome deve essere trasferito da qualsiasi parte dell'app che sta creando una nuova Persona, mentre il contenitore IOC deve passare nel Repository IPerson.

Capisco che il nome o il repository potrebbero essere iniettati usando una proprietà, ma questa non sarebbe una soluzione pulita - stiamo perdendo parte della potenza semantica del linguaggio di programmazione.

risposta

5

La classe, come sopra scritto, non sarebbe un buon candidato per l'utilizzo con un container IOC. Qui si mescolano le preoccupazioni con l'entità Persona che mantiene uno stato (il nome) ed esegue un'azione (qualunque sia il deposito utilizzato per). Se si effettua il refactoring del codice in modo che l'entità Person venga richiamata o creata tramite una classe che accetta un'implementazione di IPersonRepository tramite il costruttore, si troverà in un punto in cui l'iniezione delle dipendenze è più sensata.

+0

OK ha senso - Vedo come funzionerebbe nel mio codice – cbp

2

Sono rispettosamente in disaccordo con la risposta di Kevin McMahon di cui sopra, e il motivo è che ho visto il codice di iniezione dipendenza che fa esattamente quello che vuoi ... solo con un contenitore IoC diverso. Vale a dire, era Castle Windsor, che è un altro contenitore di Ioc. Ti permetterebbe di creare una sezione nel tuo file di configurazione per dire quali valori fornire per nome (non ha molto senso farlo per nome, ma se fosse una proprietà come "connectionString", potrebbe fare un sacco di senso).

Quindi ... non è che quello che stai cercando di fare non è adatto per l'iniezione di dipendenza in generale ... è solo che Ninject non sembra a suo agio con esso (o forse Ninject può anche adattarlo. .. Non conosco abbastanza bene tutte le sue funzioni meno usate per dirlo).

+1

In realtà penso che NInject possa farlo: ad esempio: http://stackoverflow.com/questions/1374098/with-parameters-constructorargument-with-ninject -2-0 Ma dover passare i nomi dei parametri come stringhe; non avere gli argomenti del costruttore visibili in Intellisense; nome del metodo lungo ('WithConstructorArguments') ... dammi una pausa! – cbp

8

È passato più di un anno da quando ho fatto questa domanda, e ora ne so più di quanto non facessi allora. La risposta di Kevin è corretta e buona pratica, ma a volte è necessario lavorare con le classi precedenti e voler fare qualcosa come ho nella mia domanda. Ecco come lo faccio con Ninject:

public class Person 
{ 
    [Inject] 
    public IPersonRepository PersonRepository { get; set; } 

    private string _name; 

    public Person(string name) 
    { 
     _name = name; 
     StaticKernelContainer.Inject(this); 
    } 
} 

Un'implementazione di StaticKernelContainer può essere trovato nel progetto le estensioni Web Ninject.

+1

+1 per il follow-up – ChrisWue

+0

Domanda correlata e risposta diversa qui: http://stackoverflow.com/questions/12136926/dependency-injection-with-constructor-parameters-that-arent-interfaces#comment16245407_12136926 –

Problemi correlati