依赖注入

时间:2010-09-04 13:16:35

标签: c# dependency-injection

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 个答案:

答案 0 :(得分:4)

对我来说,代码中没有违反DI的问题,关于wikipedia

  

将行为与依赖性解析分开的核心主体

但是坏的一面你的控制器有太多的知识,在某些情况下(如果你没有仔细编程)你可能会违反Law Of Demeter

看看你的代码:

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

答案 1 :(得分:2)

如果控制器需要一个IUserTasks实例,那么如果它直接从容器中收到一个实例就会更简单。从本质上讲,TaskProvider只是容器的包装器,因为它是从UserTasksIdentityTasks实例获取的。

答案 2 :(得分:2)

您正在使用依赖注入将有效的“服务定位器”注入控制器,而不是注入IUserTasks和IIdentityTasks的实现。

你的实际控制器确实依赖于IUserTasks和IIdentityTasks,但是你不是直接将它们注入你的控制器而是决定使用“服务定位器”或任务提供程序,因此你已经注入了对服务定位器的依赖,在示例中似乎只提供直接注入真正的依赖项无法完成的任何事情。

答案 3 :(得分:1)

您应该将IUserTask和IIdentityTask注入控制器的构造函数中,因为使用TaskProvider没有任何好处。除此之外,在你这样做的过程中,你会错过一些编译时检查。例如,您可以调用TaskProvider.GetTask()并等待在运行时爆炸。至少应该对该泛型参数设置一些约束(如果两个接口都可以从公共父继承)。

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