ASP.NET 5 / Core 1依赖注入:糟糕的设计或糟糕的文档?

时间:2016-04-26 05:28:32

标签: dependency-injection asp.net-core asp.net-core-mvc

我正在阅读ASP.NET 5 docs并且正在讨论依赖注入这一章。

我建议像这样写我的控制器:

public class MyController: Controller
{
    private readonly MyService _myService;

    public MyController(MyService myService)
    {
        _myService = myService;
    }

    public IActionResult Index()
    {
        // use _myService
    }
}

不鼓励短版和直接版:

public class MyController : Controller
{
    public IActionResult Index()
    {
        var myService = (MyService)HttpContext.RequestServices.GetService(typeof(MyService));
    }   
}

The given reason因为据称是推荐的版本......

  

[...]产生更容易测试的类(参见测试),并且更松散地耦合。

链接的测试章节并未阐明这一奇怪的陈述。

我没有查看源代码,但我假设控制器使用HttpContext.RequestServices.GetService本身来提供依赖项的任何构造?显然,测试可以为测试设置不同的实现,并且显然 是DI框架的重点,对吗?

巨人(MyService)HttpContext.RequestServices.GetService(typeof(MyService))已经足够糟糕,但是一个小助手可以解决这个问题(简单的Get<MyService>()真的很难吗?)。

但是,对于基本上每个控制器而言,这个过度混乱的推荐,而且更令人不安。

因为已经有一个正确使用的Microsoft DI框架,所以更令人费解的是:MEF:

public class MyController : Controller
{
    [Import]
    private MyService _myService;

    public IActionResult Index()
    {
        // use _myService
    }
}

为什么不至少拿一个?这是怎么回事?

1 个答案:

答案 0 :(得分:2)

这不是ASP.NET Core特定的解决方案。这就是每个DI框架的工作原理。最常见的方法是将控制器的所有依赖项作为构造函数参数。这清楚地表明了控制器使用的服务。有多种替代解决方案,但基本思想保持不变,并且它们有多种优缺点。

  

显然,测试可以为测试设置不同的实现,显然这是DI框架的重点,对吗?

这条线对我来说并不清楚。你认为“DI框架的全部意义”是什么?这一行建议您只使用它,以便您可以使用不同的实现进行测试。

  

但是,基本上每个控制器都推荐这种过度混乱,而且更令人不安。

过度杂乱?如果我想在两个(或更多)函数中使用MyService,该怎么办?我应该用这个:

public class MyController : Controller
{
    public IActionResult Index()
    {
        var myService = (MyService)HttpContext.RequestServices.GetService(typeof(MyService));
    }

    public IActionResult Index2()
    {
        var myService = (MyService)HttpContext.RequestServices.GetService(typeof(MyService));
    }
}

或者我应该选择在构造函数中设置的解决方案?对我来说似乎是一个明显的选择。在这么小的例子中,它可能看起来像杂乱,但添加10行代码,你几乎不会注意到一个小的构造函数和一些变量声明。

您可以在测试时使用它。这是一种在需要时快速从容器中抓取东西的方法,但它肯定不是实际代码的一部分。你只是隐藏了依赖的依赖。

最后你建议注射物业。这是一个有效的解决方案。但是经常使用的论点是它隐藏了依赖性。如果在构造函数中将其定义为参数,则无法隐藏它。此外,由于这个原因,很多DI框架甚至都不支持属性或方法注入。

如果您想在项目中使用MEF,您可以自由选择。但在我看来,它应该不是ASP.NET的默认DI框架。现在可用的功能足以完成大多数任务。如果您需要更多功能,可以随时使用不同的DI框架,例如StructureMapAutoFac

最后,一切都归结为对你有用的东西。但说明这是糟糕的设计或糟糕的文档是错误的。你当然可以自由地证明我的错误。您可以改进ASP.NET文档和/或证明控制反转的概念是错误的并提出更好的解决方案。