Costruttore Injection ha il vantaggio di rendere esplicita la dipendenza e costringe il client a fornire un'istanza. Può anche garantire che il client non possa modificare l'istanza in un secondo momento. Uno (possibile) svantaggio è che devi aggiungere un parametro al tuo costruttore.
Setter Injection ha il vantaggio di non richiedere l'aggiunta di un parametro al costruttore. Inoltre non richiede al client di impostare l'istanza. Questo è utile per dipendenze opzionali. Ciò può anche essere utile se si desidera che la classe crei, ad esempio, un repository di dati reali per impostazione predefinita, quindi in un test è possibile utilizzare il setter per sostituirlo con un'istanza di test.
Interface Injection , per quanto ne so, non è molto diverso dall'iniezione da setter. In entrambi i casi si sta (facoltativamente) impostando una dipendenza che può essere modificata in seguito.
In definitiva è una questione di preferenza e se è richiesta o meno una dipendenza . Personalmente, uso l'iniezione del costruttore quasi esclusivamente. Mi piace il fatto che renda esplicite le dipendenze di una classe costringendo il client a fornire un'istanza nel costruttore. Mi piace anche che il cliente non possa cambiare l'istanza dopo il fatto.
Spesso, la mia unica ragione per passare in due implementazioni separate è per i test. In produzione, posso passare a DataRepository
, ma in fase di test, vorrei passare a FakeDataRepository
. In questo caso di solito fornirò due costruttori: uno senza parametri e un altro che accetta a IDataRepository
. Quindi, nel costruttore senza parametri, farò una chiamata al secondo costruttore e passerò a new DataRepository()
.
Ecco un esempio in C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
Questo è noto come Poor Man's Dependency Injection. Mi piace perché nel codice client di produzione non ho bisogno di ripetermi avendo diverse dichiarazioni ripetute che sembrano
var foo = new Foo(new DataRepository());
Tuttavia, posso ancora passare un'implementazione alternativa per i test. Mi rendo conto che con DI di Poor Man sto codificando la mia dipendenza, ma questo è accettabile per me dal momento che utilizzo principalmente DI per i test.