1

我在我的项目中经常使用 DI,我对这个概念相当满意,但是有一个方面我不太确定。

所以对我来说一个常见的用例是有一个 ASP.NET MVC 控制器,我在构造函数的参数列表中列出控制器的依赖项,显然这些是在控制器由 DI 容器构造时传入的,然后我将它们分配给只读私有变量稍后由控制器中的操作使用。

现在,我担心的是,如果我只在一个动作中使用注入的依赖项(比如说 an IMemberRepository)(假设还有 5 个其他动作),我应该将其列为 ctor 中的依赖项,还是应该Container.Resolve<IMemberRepository>()在一个动作中调用动作用在哪里?

我不得不说,我确实喜欢在 ctor 中列出我的所有依赖项,而且我并不特别喜欢Container.Resolve<>()散布在我的代码中,但是,继续上面的示例,让 DI 容器实例化IMemberRepository它是没有意义的要使用的!

4

3 回答 3

3

你永远不应该在你的应用程序代码中调用 Container.Resolve。这是服务定位器模式,被认为是一种反模式。不通过构造函数注入所有依赖项意味着您隐藏了使用的依赖项,这使得类具有哪些依赖项变得不太清楚,并且使测试该类变得更加困难。

当依赖项被注入但未使用时,您担心性能,但这通常不是问题,因为对象的构造通常非常快(因为所有这些对象在构造期间应该做的是将所有传入的依赖项存储在私有字段中)。当某个类型的构造被证明太慢时,还有其他解决方案,例如将该依赖包装到延迟初始化该依赖的代理中。

如果你发现你的类获得了太多的构造函数参数,这表明它有太多的责任;它做得太多了。尝试修复课程设计中的这个缺陷,而不是退回到Container.Resolve. 例如,将一组具有类逻辑的依赖项提取到一个新类型中,并将其作为依赖项注入。

设计可能还有其他问题。当您的控制器直接依赖于存储库依赖项并且您在控制器中有业务逻辑时,您就缺少抽象。您缺少服务层。一个好的解决方案是引入命令处理程序查询处理程序

于 2012-04-24T11:20:37.340 回答
1

我赞同史蒂文所说的话。

如果有太多的构造函数参数对您不利,那么您也可以选择属性注入。我赞成这种方法。有一些对象,出于某种或其他原因,如果它们尚未完全填充,则不会被注入到属性中,而它们将被注入到构造函数中。

如果依赖项为空,我对属性的依赖项应用保护以引发异常,以便我知道它是哪个依赖项。

希望这是有道理的。

于 2012-04-24T11:33:23.547 回答
-1

我会说这取决于你想用 DI 做什么。

在构造函数中使用注入的依赖项作为参数的方法可以以很长的参数列表结束。
这对于真正的测试驱动开发可能是必要的,您可能希望模拟注入依赖项的方法。

我个人认为它会产生很多开销,因为 DI 容器总是必须构建所有依赖项,无论是否需要在 Action 中。
还需要考虑的是使用ActionsPartialViews产生更多的结构。

例如

public class HomeController : Controller
{
    private IMemberRepository _memberRepo = null;

    public HomeController(IMemberRepository repo)
    {
        _memberRepo = repo;
    }

    public ActionResult Index()
    {
        MyViewModel viewModel = _memberRepo.DoSomething();
        return View(viewModel);
    }

    [ChildActionOnly]
    public PartialViewResult SomePartialAction()
    {
        return PartialView();
    }
}

视图Index.cshtml调用局部视图SomePartialAction()的位置@Html.Action("SomePartialAction")
在这种情况下,控制器的构造函数被调用了两次。每次为每个动作。因此 DI 容器也被调用了两次。

所以这真的取决于。对于“硬核” TDD,您必须使用构造函数。否则我会在需要的地方和时间解决依赖关系。

于 2012-04-24T10:41:10.783 回答