I'm not sure if its just me, but I get the feeling that constructor injection used in ASP.NET MVC controllers is causing unnecessary resource consumption.
Components that's not being used for a particular web request still needs to be created when controllers are created. It's like buying booth milk and juice when I'm thirsty for milk and then I just throw away the juice.
Compare these examples of constructor injection and service locator for controller to clarify my concern.
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();
}
}
PLEASE NOTE that an IoC container (which is beneficial for many reasons) can still be used for the Service Locator pattern. I do not want this to be a discussion around IoC and container frameworks neither other benefits from constructor injection (clear visibilty of dependencies etc). It's the constructor injection pattern and how it wastes resources in ASP.NET MVC controller situations that is my concern.
I guess the main question here is: Is Service Locator a better solution performance wise for the above scenario (ASP.NET MVC controllers) ?
If the object creation is your bottleneck you are in either a very good situation (everything else works like a charm so the < 1 ms operations count) or in a very bad one (your constructors are doing some heavy lifting - which they are not supposed to).
Mark Seemann already covered the subject here: http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence/
In many cases that's a performance hit you'll have to take because you need those classes anyway, but sometimes you might be concerned with taking this performance hit too early. However, I make the claim that in the vast majority of cases, this concern is irrelevant.
And supplied a possible solution if it still matters to you (deferred branches).
If you don't want to construct something you don't need / use pass in something that can construct what you do need.
Using the service locator + DI in our controller factory we can pass in a dep factory to the controller and allow the controller to decide what to ask the factory for.
Is this not the reason we have the factory pattern?
So to refactor your example in the question you might want to do something like this ...
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();
}
}
This is both efficient and a good use of patterns.
From a testing point of view you can mock the passed in IDepFactory so that it always returns some constant that when queries returns a known result to allow you to confirm that your logic in your controller is behaving right.
From a performance point of view I would think that the difference depends mainly on the depth of your dependency stacks in each case, you may prefer to not use a factory and pass in both deps as you were doing before if the dependency stack is very shallow as the gains are virtually nothing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With