在asp.net mvc控制器中使用构造函数注入的IoC会浪费资源吗?

时间:2013-04-02 10:09:08

标签: asp.net-mvc dependency-injection service-locator

我不确定它是否只是我,但我感觉ASP.NET MVC控制器中使用的构造函数注入导致不必要的资源消耗。

创建控制器时,仍需要创建未使用用于特定Web请求的组件。 当我渴望喝牛奶时,就像买摊位牛奶和果汁一样,然后我就扔掉果汁。

比较控制器的构造函数注入和服务定位器的这些示例,以澄清我的担忧。

构造函数注入,创建了booth deps,但只使用了一个。

public class MyController : Controller
{
    private readonly IDep1 _dep1;
    private readonly IDep2 _dep2;

    public MyController(IDep1 dep1, IDep2 dep2)
    {
        _dep1 = dep1;
        _dep2 = dep2;
    }

    public ActionResult Index()
    {
        _dep1.MakeStuff();
        return View();
    }
    public ActionResult PageTwo()
    {
        _dep2.MakeStuff();
        return View();
    }
}

服务定位器,每个dep仅在使用时创建。

public class MyController : Controller
{
    public ActionResult Index()
    {
        var dep1 = ServiceLocator.Resolve<IDep1>();
        dep1.MakeStuff();
        return View();
    }
    public ActionResult PageTwo()
    {
        var dep2 = ServiceLocator.Resolve<IDep2>();
        dep2.MakeStuff();
        return View();
    }
}

请注意 IoC容器(由于多种原因有益)仍可用于服务定位器模式。我不希望这是围绕IoC和容器框架的讨论,也不希望构造函数注入的其他好处(清除可靠性依赖性等)。这是构造函数注入模式以及它如何浪费ASP.NET MVC控制器情境中的资源,这是我关注的问题。

我想这里的主要问题是: 对于上述场景(ASP.NET MVC控制器),Service Locator是否是更好的解决方案性能?

2 个答案:

答案 0 :(得分:8)

如果对象创建是你的瓶颈,那么你处于一个非常好的状态(其他一切都像魅力那么&#1毫秒的操作计数)或者非常糟糕的一个(你的构造者正在做一些繁重的工作 - 哪个他们不应该这样做。

马克·西曼已经在这里讨论了这个主题: http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence/

  

在许多情况下,由于你的缘故,你将不得不采取行动   无论如何都需要这些课程,但有时你可能会担心   太早取得这种表现。但是,我声称   在绝大多数情况下,这种担忧是无关紧要的。

并提供了一个可能的解决方案,如果它仍然对你很重要(延期分支)。

答案 1 :(得分:2)

如果你不想构建一些你不需要/使用的东西可以构建一些可以构建你需要的东西。

在我们的控制器工厂中使用服务定位器+ DI,我们可以将dep工厂传递给控制器​​,并允许控制器决定向工厂询问什么。

这不是我们拥有工厂模式的原因吗?

所以要在问题中重构你的例子,你可能想做这样的事情......

public class MyController : Controller
{
    private readonly IDepFactory _factory;

    public MyController(IDepFactory factory)
    {
        _factory= factory;
    }

    public ActionResult Index()
    {
        var dep1 = factory.Get<IDep1>();
        dep1.MakeStuff();
        return View();
    }
    public ActionResult PageTwo()
    {
        var dep2 = factory.Get<IDep2>();
        dep2.MakeStuff();
        return View();
    }
}

这既有效又善用模式。

从测试的角度来看,您可以模拟传入的IDepFactory,以便它始终返回一些常量,当查询返回已知结果时,您可以确认控制器中的逻辑行为正确。

从性能的角度来看,我认为差异主要取决于每种情况下依赖堆栈的深度,你可能更愿意不使用工厂并像往常一样传入两个deps,如果依赖堆栈非常浅,因为收益几乎没有。