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

在下面ITaskprovider的實施,正如你看到的IUserTask和 IIdentityTask正在從屬性,而不是構造注入。 原因是Windsor在運行時自動實例化注入屬性 ,因此我不必將所有必須注入的依賴項 都放入構造函數中。依賴注入

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

在控制器中,我在構造函數中注入ITaskProvider。

public ITaskProvider TaskProvider { get; set; } 

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

在這裏我稱之爲taskprovider及其方法很好。

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

} 

到目前爲止,一切工作正常。

我被告知,這更像是一個服務定位模式,違反了依賴注入模式,我想知道這裏違反了什麼。

回答

4

對於我來說,有一個在你的代碼對DI沒有違規,對於wikipedia

核心主要以單獨的行爲從依賴解析

但不好的一面你的控制器有太多的知識,在某些情況下(如果你沒有仔細編程),你可能違反了Law Of Demeter

看看你的代碼:

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

感謝這個有用的東西。 – Murat 2010-09-04 17:03:35

2

如果控制器需要一個IUserTasks實例,那麼如果它直接從容器中收到一個實例,則會更簡單。實質上,TaskProvider只是一個容器的包裝,因爲它是從中獲取UserTasksIdentityTasks實例的地方。

+0

是的,這只是一個包裝。它是否仍然違反依賴注入模式? – Murat 2010-09-04 14:15:28

+1

@穆拉特 - 如果它被注入到它的家屬中並不是真正的違法行爲,它只是沒有提供任何價值。 – Lee 2010-09-04 14:25:14

2

您正在使用依賴注入將有效的「服務定位器」注入控制器,而不是注入IUserTasks和IIdentityTasks的實現。

您的實際控制器確實依賴於IUserTasks和IIdentityTasks,但您並不是直接將這些注入到控制器中,而是決定使用「服務定位器」或任務提供程序,因此您已在服務定位器中注入了依賴關係示例似乎沒有提供任何通過直接注入真正依賴關係無法完成的事情。

1

您應該將IUserTask和IIdentityTask注入到控制器的構造函數中,因爲使用TaskProvider沒有任何好處。除此之外,按照你所做的方式,你會錯過一些編譯時間檢查。例如,您可以調用TaskProvider.GetTask()並等待在運行時爆炸。您至少應該對該泛型參數施加一些限制(如果可能的話,這兩個接口都可以從公共父級繼承)。

關於「違規」,你應該注意到你沒有注入依賴關係到控制器中。您正在提供一種方法來檢索它們。