What is Dependency Injection?
The simplest explanation that one could give is – separate the responsibility of resolving object dependency from its behavior.
To get an idea on why we are going to adapt this pattern, lets take a look at an example with out DI. We will start with the classic three-layered web application.
These arrows show the way the dependency is on the layer. View Layer is dependent on Domain Layer and Domain Layer is dependent on the Data Access Layer. The layers represent a separate project in the solution.
This looks all good from the outside but when it comes to making changes in the Data Access Layer and the View Layer would have to make references to the DAL directly. Now the references all get changed like this,
This becomes a menace as we have lost control of the Data Access Layer and there is nothing to stop the newbie developer in calling the Data Access Layer directly and writing a fancy loop in the code to change data. This becomes a messy situation to handle as all the Business Layer is all over the place and layering has gone for a toss.
Dependency Injection is the SOLUTION here!
Dependency Injection means sending a dependency (Data Access Layer) into a dependent object (Domain Layer) as opposed to the dependent object controlling life cycle of its dependencies.
That seems like a text book definition isn’t it, we’ll break it down. This basically means Domain Layer should not instantiate Data Access Layer, instead of that correct data access instance should be passed to it. Does it mean View Layer will pass the instance to Data Access Layer, No. View Layer will have to delegate the instantiation via a special class called Composition Root. The Composition Root will use a Factory to determine the correct instance and will also create a dependency using Reflection and pass it on to View Layer.
To make the abstraction look complete, the Business Layer should define an abstract class or an interface for the Data Access Layer to implement. This will prevent code instantiation of Data Access Layer anywhere in the Business or View Layer. Now the design diagram changes to,
If we notice that Domain Layer is no longer coupled to Data Access Layer, DAL now refer to the Domain Layer. Because Domain Layer defines the Interfaces that are implemented by the DAL Layer.
This looks good for the dependency creation, to deal with UI dependency on the data – we have to come up with Data Objects (DO). POCO (Plain Old CLR Objects) classes will be defined where Repository implementation will translate the persistent entity objects in DAL Layer to Domain POCOs.
Step 1: We start off with Domain layer
Add Domain entities to interact with the View layer thus disconnecting View layer and data layer dependency.
Add reference to System.ComponentModel.DataAnnotations. Add a folder called Model and add a class called BlogPost.cs.
The class looks like the following
Add a repository Interface to replace the coupling with Data Access layer. All data access calls will be made to the interface. The Interface has the following contract methods.
Step 2: Creating the Data Access Layer
- We will create a new project for the explanation and add in the Nuget reference for EntityFramework.
- Add a folder Context and move cs from the DISample.Models folder to this new folder.
- Add a folder Model and move the cs from the DISample.Models folder to this new folder.
Add a new method ToDomainBlogPost() that returns the Domain entity for the current Data entity. The ToDomainBlogPost() entity is a mapping method from a Data object to a Domain object.
The final code looks as follows
- Add a folder Repository
Add the class SqlBlogPostRepository that implements IBlogPostRepository. The final implementation looks as follows. Note, for the Add and Update methods we are mapping the Domain object coming from View, into a Data object.
This completes the data layer implementation.
Step 3: The Composition Root
With the data layer and domain layer in place, first we’ll get the code to build and then we will then implement the dependency injection part. We will update the BlogPostController as follows:
- Add a class level instance variable of type IBlogPostRepository
private IBlogPostRepository _repository;
- Remove all instances of db context and replace them with appropriate repository method calls.
- Build the solution. Interestingly enough, the solution will build correctly. But if we run it we’ll get a null reference exception for _repository because we have not instantiated with a concrete instance.
- As discussed briefly earlier, the way to delegate responsibility is to pass the dependencies through constructor injection. The BlogPostController does not have a constructor so we will add one as follows
- As we can see above our controller now expects the _repository to be provided (injected with) a repository instance.
- However, the MVC Framework calls the BlogPostController and by default it expects an empty constructor. So how will we inject our dependency? MVC is a mind blowingly pluggable framework. You have to create a custom Controller Factory that derives from the DefaultControllerFactory. The class code is as follows
- Let us look at the factory class closely
- It has a dictionary for storing the controllers.
- The constructor is still taking a parameter of type repository (so we will be injecting the dependency into the controller factory as well).
- The constructor has a ‘guard method’ to ensure that repository parameter is not null.
- It then initializes the controller map and adds the two controllers that we have Home and Blog.
- We next override the CreateController method to return correct controller based on the controllerName and requestContext.With the BlogControllerFactory in place we have ironed out the Constructor injection for the MVC controller. All that is remaining is creation of the CompositionRoot and hooking it up with the application start
- The CompositionRoot class can be just called so. Add it to the root of the DISample You could create a new project or folder for it too, but doesn’t really matter.
- The implementation of the CompositionRoot class is simple. The code listing is as follows
- There is a local instance variable of the controllerFactory of type IControllerFactory
- The constructor is public and without parameters. It calls a private static method CreateControllerFactory().
- The CreateControllerFactory() method is where our dependency instantiation happens.
- It picks up the Type name from Config’s AppSettings section.
- Gets the Type by name
- Builds an instance using CreateInstance. Notice how we don’t know the instance type at any point because the CompositionRoot is only aware of the Interface. So, we cast the instance back as the interface only.
- This instance is used to instantiate the BlogContollerFactory
- Returns the BlogControllerFactory to the constructor, that’s saved in the local controllerFactory
Update the config and add the type name
<add key=”BlogRepositoryType” value=”DISample.Data.Repository.SqlBlogPostRepository, DISample.Data”/>
Now all that remains is using the CompositionRoot and letting MVC know that it should use our ControllerFactory instead of the default one. We do this in the Application_Start() event as follows
We initialize the Composition Root. We get the Current ControllerBuilder (provided by the MVC framework) and call the SetControllerFactory method by passing the ControllerFactory from the composition root.
Update all the Blog Views to refer to Domain.Model.BlogPost instead of DISample.Models.BlogPost.
Finally, remember the View layer doesn’t have access to the Data Layer. It uses reflection to generate the dependency, so the Data layer dll must be available as a part of the build. To make that happen add a build event for the solution that copies over the Data.dll over to the View’s bin folder. The command is as follows.
copy “$(SolutionDir)FunWithSignalR.Data\bin\$(ConfigurationName)\*.dll” “$(TargetDir)”
Dependency Injection – Recap
Dependency Injection is a Design pattern that enables us to write loosely coupled code and enforces, dependent object gives up control of managing their dependencies and instead let a Composition Root inject the dependencies into them.
Using a Composition Root in a manner described above is often referred to as Poor man’s DI pattern. This is not so much of a bad thing as it is an indicator of lack of Inversion of Control Containers. IoC Containers help in taking away the pain of registering each new object and managing their instances. Some common IoC containers for .NET are Castle Windsor, Unity, Ninject.
DI + Repository + Programming against Interfaces overall help in separation of concerns and greatly improves the overall application maintainability.
The above design has zero impact on change to View or Data layer.
For example, if we were to introduce a new Mobile view we could simply go and build it from scratch while using the exact same Domain and Data Access Layer. All we had to do was ensure the dependencies are created correctly at the Composition Root.
Similarly, to swap the Sql backend with an Azure backend there would be zero impact on the business layer or the View layer. All that would change was the configuration information providing the concrete type for the Azure repository implementation.
In any other design the impact of such changes is much more pervasive and requires touching all layers of an application.
Taking a little bit of time to learn about design patterns prepare us to better recognize practical scenarios of application. Dependency Injection in my book is one of the most important patterns for a seasoned ASP.NET MVC developer. It helps layout a truly flexible, decoupled foundation for what seems a simple problem but will most certainly become a very complex application in future.
Dependency Inject in .NET By Mark Seemann