2010-09-04 21 views
9
public interface ITaskProvider 
{ 
    T GetTask<T>(); 
} 

Bei der Implementierung von ITaskprovider unten, wie Sie die IUserTask und IIdentityTask sehen anstelle von Konstruktor von Immobilien injizieren. Der Grund ist, dass Windsor automatisch die injizierten Eigenschaften zur Laufzeit instanziiert, wenn auf sie zugegriffen wird, so dass ich nicht alle Abhängigkeiten des Müssen injizierten im Konstruktor setzen muss.Dependency Injection

public class TaskProvider : ITaskProvider 
    { 
     public IUserTasks UserTasks { get; set; } 

     public IIdentityTasks IdentityTasks { get; set; } 

     public T GetTask<T>() 
     { 
      Type type = typeof(T); 
      if (type == typeof(IUserTasks)) return (T)this.UserTasks; 
      if (type == typeof(IIdentityTasks)) return (T)this.IdentityTasks; 

      return default(T); 
     } 
    } 

In der Steuerung injiziere ich den ITaskProvider im Konstruktor.

public ITaskProvider TaskProvider { get; set; } 

public AuctionsController(ITaskProvider taskProvider) 
     { 
      TaskProvider = taskProvider; 
     } 

Und hier rufe ich den Taskprovider und seine Methoden in Ordnung.

public ActionResult Index() 
{ 
var userTasks = TaskProvider.GetTask<IUserTasks>(); 
var user = userTasks.FindbyId(guid); 

} 

Bis hierher, funktioniert alles einwandfrei.

Mir wurde gesagt, dass dies mehr wie ein Service-Locator-Muster ist und verletzt Abhängigkeit Injektion Muster und ich möchte wissen, was hier verletzt.

Antwort

4

Für mich gibt es keine Verletzung gegen DI im Code, in Bezug auf wikipedia:

Kern Haupt zu trennen Verhalten von Abhängigkeitsauflösung

Aber die schlechte Seite des Controllers hat zu viel Wissen in einigen Fällen (wenn Sie keine Programme sorgfältig tun) Sie können die Law Of Demeter

verletzen einen Blick auf den Code nehmen:

public ActionResult Index() 
{ 
var userTasks = TaskProvider.GetTask<IUserTasks>(); 
var user = userTasks.FindbyId(guid); 
} 
+0

Danke für dieses nützliche Zeug. – Murat

2

Wenn der Controller eine IUserTasks Instanz benötigt, dann wäre es einfacher, wenn er einen direkt vom Container erhält. Im Wesentlichen ist die nur ein Wrapper um den Container herum, denn hier bekommt er die UserTasks und IdentityTasks Instanzen von.

+0

Ja, das ist nur ein Wrapper.Verstößt es immer noch gegen das Abhängigkeitsinjektionsmuster? – Murat

+1

@Murat - Es ist nicht wirklich eine Verletzung, wenn es in seine Angehörigen injiziert wird, es bietet nur keinen Wert. – Lee

2

Sie verwenden Dependency Injection, um den "Service Locator" in den Controller zu injizieren, anstatt eine Implementierung von IUserTasks und IIdentityTasks zu injizieren.

Ihr tatsächlicher Controller hat wirklich Abhängigkeiten von IUserTasks und IIdentityTasks, aber Sie injizieren diese nicht direkt in Ihren Controller, sondern entscheiden sich für den "Service Locator" oder Task Provider und deshalb haben Sie eine Abhängigkeit vom Service Locator eingefügt Beispiel scheint nichts zu bieten, was nicht durch direktes Einfügen der wahren Abhängigkeiten erreicht werden könnte.

1

Sie sollten IUserTask und IIdentityTask in den Konstruktor des Controllers einfügen, da der TaskProvider nicht genutzt wird. Außerdem vermissen Sie in der Art, wie Sie es gemacht haben, einige Compile-Time-Checks. Beispielsweise könnten Sie TaskProvider.GetTask() aufrufen und warten, bis zur Laufzeit explodiert. Sie sollten diesem generischen Parameter zumindest eine Einschränkung auferlegen (wenn es möglich ist, dass beide Schnittstellen vom gemeinsamen übergeordneten Element erben).

In Bezug auf die "Verletzung" sollten Sie beachten, dass Sie die Abhängigkeiten nicht in den Controller injizieren. Sie bieten eine Möglichkeit, sie abzurufen.