2010-09-04 323 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()并等待在运行时爆炸。您至少应该对该泛型参数施加一些限制(如果可能的话,这两个接口都可以从公共父级继承)。

关于“违规”,你应该注意到你没有注入依赖关系到控制器中。您正在提供一种方法来检索它们。