Thank you everyone for your valuable feedback and awesome response on my last post on Repository Pattern. In this post, we will see what Dependency Injection is and how to implement it, we will try to use some of the frameworks available to achieve the same.
Introduction
Dependency Injection is a design pattern, which implements Inversion Of Control(IoC) for resolving dependency. So what it means, it helps us in implementing loose coupling between our objects. The terms tightly coupled and loosely coupled, is used many times while working in our application. Let’s see what these 2 terms means
Tightly Coupled System
We are always advised to create a system which is not tightly coupled, a tightly coupled system is where all objects are tightly coupled to each other, if you want to remove one sub-System from our application, it will require many changes across the application, and sometimes writing almost the entire code again. If you have used logging system in any application like log4Net, we always write code in our client code where we want to log something, just imagine if tomorrow we want to replace the logging with DB logger. We need to replace all code, just think about the time wasted in such a boring task, replacing an object in all classes, I am sure no one wants to do that.
Loosely Coupled System
The answer to avoid the above issue is creating loosely coupled system, where we are easily able to replace a similar object easily.
Now we are aware of what we want to achieve, let’s go ahead and implement DI using unity framework and MVC. There are many DI containers available, we will cover most of them in future posts.
Prerequisites
We will be using the below given IDE and Frameworks in this blog:
- VS 2015
- Entity Framework 6.0
- MVC controller
- Class Library Project
We will create a WebApi
project and consume the Repository layer directly in our API controllers to see it working, in real life project, please have a service layer in between. So let’s get started and create our project.
- Create a project. Go to File->New->Project, name it as
StudentApp
and click OK. Choose ASP.NET Web Application.
- On Next page, create MVC from templates, an select Web API from “Add folders and core references for”, MVC will be selected by default, click OK to wait for some time, your project will be loaded.
- Now once our project is loaded, let’s see what things we need to make it work, as informed we will create a different project to create our Repository Layer.
- Leave your project as it is and a new project, right click on solution and Add->New Project and choose Class Library, name it as
StudentApp.Repository
and click ok. - Let’s add Entity Framework as reference to our project, we will use NuGet, so right click on this recently created project and click Manage NuGet Packages and goto Browse tab and search for
EntityFramework
and install, it will ask to accept, click accept and references will be added. - In Entity Framework, we create context classes which connects to your database, there are 2 options, we can use a single context class and all Models or we can create each context for every Models available.
- For database, we will be using
localDb
, if you open your web.config file from studentApp
, we will find a DefaultConnection
as connectionString
, we will change the database name and change it to StudentDataBase
. - Now, we need one more project for our Models, let’s add a new
ClassLibrary
project and name it as StudentApp.Model
.
- Project will be loaded with Class1.cs, let’s rename the class and change it to
Student
, it will ask whether you want to rename all references, say yes. - Now add few properties to our class, we will see the advantages of entity framework as well.
namespace StudentApp.Model
{
public class Student
{
public int StudentID { get; set; }
public string FristName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? ModeifiedDate { get; set; }
}
}
- Done with our model class, now build our model project and add reference of this project to our Repository. To add, just right click on our Repository project Add-> reference, a box will open from left side choose Project. It will show us 2 options, choose
StudentApp.Model
and click OK.
- In our Repository project, rename the class1.cs file to StudentContext.cs. So if you are thinking what
context
class does, it is the model which will talk to our database and help us retrieve the data from DB, let DB know which are the tables DB needs to create, with which properties and which database to target. - To create out
StudentContext
, we need to inherit DbContext
class, our default constructor will have parameter which will be connectionString Name
from our config class. Let’s see the code below.
namespace StudentApp.Repository
{
public class StudentContext : DbContext
{
public StudentContext() : base("DefaultConnection")
{
}
public DbSet<Student> Student { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
- Line number 5 has the default constructor which will initialize our database, the parameter passed is the same as our
connectionString Name
. - Line number 10 has the property as
Student
, DbSet<>
tells the database that we need to create a table with name as Student
in our database and onModelCreating()
method, let’s modify properties to table before table is created in DB. - As already informed in the introduction, repository pattern creates an abstraction between Service and data access layer, it means there will be
interface
or abstract
class that is involved. - Let’s create a folder as
Interface
, we will add all interfaces in this folder. So let’s add our interface called IStudentRepository
and 2 methods as “Get
” and “Add
”.
using StudentApp.Model;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace StudentApp.Repository.Interface
{
public interface IStudentRepository
{
Task<List<Student>> Get();
Task<bool> Add(Student student);
}
}
- Now, we need to implement the
interface
as well, let’s add a class called StudentRepository
and implement the IStudentRepository
.
using StudentApp.Model;
using StudentApp.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Threading.Tasks;
namespace StudentApp.Repository
{
public class StudentRepository : IStudentRepository
{
private StudentContext _context = new StudentContext();
public StudentRepository(StudentContext context)
{
this._context = context;
}
public async Task<List<Student>> Get()
{
return await _context.Student.ToListAsync();
}
public async Task<bool> Add(Student student)
{
student.CreatedDate = DateTime.Now;
_context.Student.Add(student);
int x = await _context.SaveChangesAsync();
return x == 0 ? false : true;
}
}
}
- If you notice line number 14 , we are passing
StudentContext
as parameter in StudentRepository
class, this is called Construction injection. - As discussed in the previous blog, in the real world project, it's always good to have service layer between your controller and Repository. So let’s go ahead and add a service layer as well.
- Right click on solution and add new project, name it as
StudentApp.Service
, rename the class1.cs as StudentService
, also add a new folder Interface
and add a new interface IStudentService
into that folder. - We will add the same two methods,
Get
and Add
in our interface.
using StudentApp.Model;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace StudentApp.Service.Interface
{
public interface IStudentService
{
Task<List<Student>> Get();
Task<bool> Add(Student student);
}
}
- Now let’s inherit this interface into our
StudentService
, we will call our repository from this layer rather than from controller, we will have one more level of abstraction between our UI and Repository. - To access repository, we need to add create some instance into this class right. Let's go ahead and create an instance:
using StudentApp.Model;
using StudentApp.Repository.Interface;
using StudentApp.Service.Interface;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace StudentApp.Service
{
public class StudentService : IStudentService
{
private IStudentRepository __repo;
public StudentService(IStudentRepository repo)
{
this.__repo = repo;
}
public async Task<bool> Add(Student student)
{
return await __repo.Add(student);
}
public async Task<List<Student>> Get()
{
return await __repo.Get();
}
}
}
- If you notice the constructor
StudentService
, it has IStudentRepository
as parameter, which is called constructor injection, as we saw above with studentContext
, but we are not creating any instance of StudentRepository
class, isn’t it strange as we are aware we need to create the instance of class, interface only holds the definition of methods, this is the beauty of DI. - If you compile this project now, it will be compiled, but it will throw an error if you try to call any method, let’s see how to resolve the dependency using Unity.
- Now in our
StudentApp
project, add reference and choose StudentApp.Service
and StudentApp.Model
. - Now let’s move ahead and add a new controller called as
StudentController
, to add Right click on Controller folder and Add-> Controller select MVC5 controller – Empty and name it as StudentController
. - We will have 2 Actions as
Get
and Post
:
using StudentApp.Model;
using StudentApp.Service.Interface;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace StudentApp.Controllers
{
public class StudentController : Controller
{
private IStudentService _service;
public StudentController(IStudentService service)
{
this._service = service;
}
[HttpGet]
public async Task<JsonResult> Get()
{
return Json(await _service.Get(), JsonRequestBehavior.AllowGet);
}
[HttpPost]
public async Task<bool> Post(Student student)
{
return await _service.Add(student);
}
}
}
Similar to our service, we have a constructor injection we are injecting the IStudentService
, here also we are not creating instance of StudentService
, if you compile this solution now it will be built, but will throw the exception if you try to call any action.
- Now let’s go ahead and add Unity for MVC, right click on
StudentApp
project and select Manage Nuget Packages, go to Browse tab and search for Unity select Unity.MVC and click install.
- Once this is installed, this will add 2 files, UnityConfig.cs and UnityMvcActivator.cs class. You can find both the classes in App_Start folder.
- We only need to make changes into UnityConfig.cs file, so open the same and find the
RegisterTypes
method. If you notice, there are some comments, there are 2 options to configure DI (Dependency Injection) either using web.cofig file or using code. We will see the second option using code. - You will find
just below that add, we will configure our classes.
using Microsoft.Practices.Unity;
using StudentApp.Repository;
using StudentApp.Repository.Interface;
using StudentApp.Service;
using StudentApp.Service.Interface;
using System;
namespace StudentApp.App_Start
{
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer>
container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IStudentService,StudentService>();
container.RegisterType<IStudentRepository, StudentRepository>();
}
}
}
- Notice line numbers 43 and 44.
- Now let’s press F5 and see the result.
- Let’s see the same result for
Get
.
- We can achieve the same using config file.
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<container>
<register type="StudentApp.Service.Interface.IStudentService,
Services" mapTo="StudentApp.Service.StudentService, Services" />
<register type="StudentApp.Repository.Interface.IStudentRepository,
Services" mapTo="StudentApp.Repository.StudentRepository, Services" />
</container>
</unity>
- If we add a debugger on
StudentController
constructor, and go to immediate window, and write this._service
, we will get
{StudentApp.Service.StudentService}<br />
__repo: {StudentApp.Repository.StudentRepository}
, here we are getting the actual objects.
Conclusion
So what did we achieve here, it gives the solution to our actual problem discussed isn’t it.
There are several advantages as well, which you might have noticed if you are still creating the class object and using it. Below are few of them:
- Reduces class coupling
- Code reuse
There are several other containers available as well.
- spring.Net
- StructureMap
- Ninject
and many others, just keep one thing in mind, if you want to choose one of them, choose any one which you like.
You can get the code below:
Thanks for reading this post, you can mail me at santosh.yadav198613@gmail.com, in case of any question. You can follow my Facebook page as well here. You can follow me on twitter as @santosh007india.