As a prerequisite to reading this blog I would strongly suggest you review the “.NET Web Development and Tools” blog on this topic at Dependency Injection in ASP.NET vNext.
We live in an agile world which gives us the opportunity to work with the latest and greatest as it unfolds. As such I found the above link helpful, but not complete as the latest videos on this topic (as of this writing) suggest that we have to return our IServiceProvider implementation from ConfigureServices – which is by default a void method. In addition to videos I found the blog on using Autofac IOC container that provided more clues, but still fell short….
My research found that it will be the DI container authors responsibilities to make the necessary adapters for their respective containers (as Autofac did). If you are like me and don’t want to be blocked, nor code in a lot of technical debt until the DI container vendor creates their service provider adapter for ASP.NET MVC, I offer a “poor man” adapter that will get the job done so that you can code against your favorite DI container.
The shortfall eluded to above was that the ASP.NET MVC 6 template had a lot of code in it and simply returning my Unity Service Provider was a more daunting task (reference method in image below). A task that required me to dig into the source code to figure out how to create and implement my own provider.
SOURCE CODE: contains two classes and an interface in => Unity.Framework.DependencyInjection.zip
(project has dependencies DependencyInjection beta 6)
BUG: There is a bug in MVC beta 6 that causes the default provider to be returned even if a new/different
implementation is returned by ConfigureServices. Reported here with work-around
The following Startup code shows the updated source for my POC highlighted in a yellow box. I should note that without line 98 my HomeController (which has dependency property requiring setter injection by Unity) will never be seen by the IServiceProvider implementation – the controller will be “new’d” up versus resolved.
The code comments will make the remaining code self explanatory – I’ll just add that the UnityContainerManager wires up the UnityServiceProvider (these two classes are all that are required).
I take a rather simplified approach that allows the developer to use both the default IOC container while providing their own (has less moving parts and places for failure). When you review the UnityServiceProvider class code you’ll find that I first try to resolve types using the default MVC service provider and if successful return its value, IF NOT SUCCESSFUL I’ll use the Unity Container to resolve the type – this works because I have no plans or intentions of modifying Microsoft code (even though it is open source) to where I’ll need to inject my components into them. If I require any default framework implementation, i.e., logging, then I’ll inject an instance into my container when I register other implementation (reference line 113 above).
The “cool” part of this process was that I would need to change the default return value of ConfigureServices from “void” to “IServiceProvider” and it would know how to use my provider. I connected to the source code, put a break point at the end of CreateServices and when I stepped out the calling process gave me the information I needed; BuildServiceProvider (line 106 above). On line 41 below, if CreateServices is void it will return null resulting in a default service provider being constructed using BuildServiceProvider, otherwise it returns the provided instance – so whether void or not it returns an instance of IServiceProvider.
Note the blue highlighted line in above image (bottom Locals pane): if I had not taken the simplified approach of using both default and Unity service providers I would be responsible for transferring the 241 interface, scope, and implementations into my container.
To simplify code I decided to register my Unity container manager with the “default” service provider (line 103 below), build the Service Provider for default services (line 106), and then resolve my IUnityContainerManager implementation on line 110.
I did this to save some coding steps, this effectively allows me to grab an instance of the default MVC service provider via constructor injection in my UnityContainerManager (reference below line 30). Note on line 43 that I effectively store the default service provider in “my” Unity container with a named parameter so that I can retrieve it in my UnityServiceProvider.
This keeps my Unity service provider compact and lightweight as shown below. On lines 23-30 I attempt to resolve the type using the built-in (default) service provider (which in my POC has 241 registrations). If the value is not null then I use the Unity container’s BuildUp method so that any dependency properties will be injected (setter injection); this is required for Controllers setter injection. If null is returned I then use my Unity container (line 46) to resolve the type.
IMPORTANT NOTE: Controller constructor injection will utilize the ASP.NET MVC default service provider – not the Unity service provider. After the default service provider resolves the controller (line 30 below) the Unity Container will perform a BuildUp (line 39) effectively setting any dependency properties registered in the Unity container.
Below is the final result of my POC