我不确定它是否只是我,但我感觉ASP.NET MVC控制器中使用的构造函数注入导致不必要的资源消耗。
创建控制器时,仍需要创建未使用用于特定Web请求的组件。 当我渴望喝牛奶时,就像买摊位牛奶和果汁一样,然后我就扔掉果汁。
比较控制器的构造函数注入和服务定位器的这些示例,以澄清我的担忧。
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();
}
}
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是否是更好的解决方案性能?
答案 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,如果依赖堆栈非常浅,因为收益几乎没有。