3

How does construction work with dependency injection?

With the following code:

public class AdvancedSearchController : Controller
{
    private EmployeeController _employeeController;

    public AdvancedSearchController(EmployeeController employeeController)
    {
        _employeeController = employeeController;
    }

When and how does the employeeController in the code above get set or passed into the constructor? How does this magic happen?

4
  • Someone has to invoke the AdvancedSearchController constructor and pass an EmployeeController object into it, or else this code simply never do anything and/or fail to compile. It's the same as any other class.
    – Ixrec
    Commented Jan 8, 2016 at 23:34
  • I'm no MVC guru, but I know you can configure Web API so that Controllers are instantiated by an IoC container. This allows you to have Controllers with construction dependencies still get automagically instantiated for each web request. AFAIK it's not out-of-the-box behaviour, but it's still very common.
    – MetaFight
    Commented Jan 8, 2016 at 23:37
  • 3
    @Ixrec this is actually a question about how the MVC framework (it's all bundles together) knows how to construct his controller (his code never constructs his controller, ASP.NET MVC controllers are constructed by the framework). The answer is the ASP.NET MVC framework has a built in IoC container which you need to instruct on how to construct controller dependencies. It's called DependencyResolver and the MSDN is here. I believe you set your MVC applications resolver on the config object. Commented Jan 9, 2016 at 6:15
  • MVC 5 or MVC 6?
    – ngm
    Commented Jan 9, 2016 at 13:33

2 Answers 2

7

There's no magic unless you consider dependency injection magic. If you dig around in that app's start-up/bootstrap code, you'll almost certainly find an IoC container. Look in Global.asax.cs and follow the paths from your application start event handler. You'll find component/service registration in there somewhere. Sometimes it's right in the Global.asax, sometimes it's stored in App_Start, sometimes it's in the root, and sometimes it's elsewhere. It's there, though.

The latest versions of ASP.NET ship with built-in dependency injection. The latest versions of MVC put it to use.

If you're using an older framework, there are many third-party containers. A few examples:

The principle is simple. You register some concrete type as the active representation of a contract. (The contract is usually an interface, but could also be a concrete type.) Then in code, you always refer to things as contracts. The container gives you the registered type, but you don't have to think about the details. This makes it easy to swap out implementations in one and only one place. Which in turn makes it easy to do things like test pieces of code using predictable mock objects versus using unpredictable, complex objects. Complex objects make it difficult to understand what you're really testing.

In addition to registering types as contracts, IoC containers also do fancy things like automatically inject types into managed components. That's what you're seeing in your example. The container is managing your controllers, so it knows to provide an EmployeeController to your AdvancedSearchController. Who knows? Maybe it injected some other type into the EmployeeController before it passed it on. (You didn't ask, but I'm not crazy about passing controllers around. If you have any say in the matter, ditch it. Replace it with some non-controller that does the needed work. Controllers should only knit models to views. )

Some containers also let you decide the lifetime of your registered types -- maybe they're instantiated each time they're used, maybe an object sticks around for the duration of a web request (slick for managing a unit-of-work in a web service), or maybe there's only ever just one.

0
0

If you are using ASP.NET Core MVC this is how it works: You must register your types in the ConfigureServices method of the Startup.cs class. The ConfigureServices method gets called by the runtime and add services to the dependency injection container. If you don’t register it here, then when the controller is called it will give an error. It will still build but will return an error when the controller is initiated by someone going to that URL. Since your object is registered, that is the one which will be injected into the controller.

So, why is this useful? Your startup.cs class should have something such as services.AddTransient<IEmployeeController, EmployeeController>(); Let’s say you wanted to use fake data to test something out. You would change that one line to services.AddTransient<IEmployeeController, EmployeeControllerFakeData>();

The class EmployeeControllerFakeData would just have some hard-coded data you want to test. Since you now registered the EmployeeControllerFakeData that is the one which will be injected into the constructor.

You are taking the dependency it needs, whether that be test data, oracle data, sql data, data from a file etc. and registering it, so that it’s injected where it’s needed.

Not the answer you're looking for? Browse other questions tagged or ask your own question.