Konstruktorinjektion hat den Vorteil, dass sie die Abhängigkeit explizit macht und den Client zwingt, eine Instanz bereitzustellen. Es kann auch garantiert werden, dass der Client die Instanz später nicht ändern kann. Ein (möglicher) Nachteil ist, dass Sie Ihrem Konstruktor einen Parameter hinzufügen müssen.
Setter Injection hat den Vorteil, dass dem Konstruktor kein Parameter hinzugefügt werden muss. Es ist auch nicht erforderlich, dass der Client die Instanz festlegt. Dies ist nützlich für optionale Abhängigkeiten. Dies kann auch nützlich sein, wenn Sie möchten, dass die Klasse standardmäßig beispielsweise ein reales Datenrepository erstellt. In einem Test können Sie den Setter dann verwenden, um ihn durch eine Testinstanz zu ersetzen.
Interface Injection ist , soweit ich das beurteilen kann, nicht viel anders als Setter Injection. In beiden Fällen legen Sie (optional) eine Abhängigkeit fest, die später geändert werden kann.
Letztendlich ist es eine Frage der Präferenz und ob eine Abhängigkeit erforderlich ist oder nicht . Persönlich verwende ich fast ausschließlich Konstruktor-Injection. Mir gefällt, dass dadurch die Abhängigkeiten einer Klasse explizit werden, indem der Client gezwungen wird, eine Instanz im Konstruktor bereitzustellen. Mir gefällt auch, dass der Client die Instanz nicht nachträglich ändern kann.
Oft ist mein einziger Grund, zwei separate Implementierungen zu übergeben, das Testen. In der Produktion kann ich eine DataRepository
Prüfung ablegen, aber beim Testen würde ich eine Prüfung ablegen FakeDataRepository
. In diesem Fall stelle ich normalerweise zwei Konstruktoren zur Verfügung: einen ohne Parameter und einen anderen, der a akzeptiert IDataRepository
. Dann werde ich im Konstruktor ohne Parameter einen Aufruf an den zweiten Konstruktor ketten und a übergeben new DataRepository()
.
Hier ist ein Beispiel in C #:
public class Foo
{
private readonly IDataRepository dataRepository;
public Foo() : this(new DataRepository())
{
}
public Foo(IDataRespository dataRepository)
{
this.dataRepository = dataRepository;
}
}
Dies ist als Poor Man's Dependency Injection bekannt. Ich mag es, weil ich mich im Code des Produktionsclients nicht wiederholen muss, indem ich mehrere wiederholte Anweisungen habe, die aussehen
var foo = new Foo(new DataRepository());
Ich kann jedoch immer noch eine alternative Implementierung zum Testen übergeben. Mir ist klar, dass ich mit Poor Man's DI meine Abhängigkeit fest codiere, aber das ist für mich akzeptabel, da ich DI hauptsächlich zum Testen verwende.