Home > Architecture > Dependency Injection using Unity

Dependency Injection using Unity


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:

  1. VS 2015
  2. Entity Framework 6.0
  3. MVC controller
  4. 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.

  1. Create a project. Go to File->New->Project, name it as StudentApp and click OK. Choose ASP.NET Web Application.Project.JPG
  2. 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.1114179/Template.jpg
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. Now, we need one more project for our Models, let’s add a new ClassLibrary project and name it as StudentApp.Model.1114179/Models.jpg
  9. 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.
  10. 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; }
        }
    }
  11. 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.Reference
  12. 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.
  13. 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 { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }
        }
    }
  14. Line number 5 has the default constructor which will initialize our database, the parameter passed is the same as our connectionString Name.
  15. 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.
  16. 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.
  17. 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> Get();
             Task Add(Student student);
        }
    }
  18. 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> Get()
            {
                return await _context.Student.ToListAsync();
            }
    
            public async Task Add(Student student)
            {
                student.CreatedDate = DateTime.Now;
                _context.Student.Add(student);
                int x = await _context.SaveChangesAsync();
                return x == 0 ? false : true;
            }
        }
    }
  19. If you notice line number 14 , we are passing StudentContext as parameter in StudentRepositoryclass, this is called Construction injection.
  20. 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.
  21. 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.
  22. 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> Get();
            Task Add(Student student);
        }
    }
  23. 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.
  24. 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 Add(Student student)
            {
                return await __repo.Add(student);
            }
    
            public async Task<List> Get()
            {
                return await __repo.Get();
            }
        }
    }
  25. 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.
  26. 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.
  27. Now in our StudentApp project, add reference and choose StudentApp.Service and StudentApp.Model.
  28. 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.
  29. 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 Get()
            {
                return Json(await _service.Get(), JsonRequestBehavior.AllowGet);
            }
    
            [HttpPost]
            public async Task 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.

  30. 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.Nuget
  31. 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.
  32. We only need to make changes into UnityConfig.cs file, so open the same and find the RegisterTypesmethod. 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.
  33. You will find // TODO: Register your types here
    // container.RegisterType<IProductRepository, ProductRepository>();
    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
    {
        /// <summary>
        /// Specifies the Unity configuration for the main container.
        /// </summary>
        public class UnityConfig
        {
            #region Unity Container
            private static Lazy 
            container = new Lazy(() =>
            {
                var container = new UnityContainer();
                RegisterTypes(container);
                return container;
            });
    
            /// <summary>
            /// Gets the configured Unity container.
            /// </summary>
            public static IUnityContainer GetConfiguredContainer()
            {
                return container.Value;
            }
            #endregion
    
            /// <summary>Registers the type mappings with the Unity container.</summary>
            /// <param name="container">The unity container to configure.</param>
            /// <remarks>There is no need to register concrete types 
            /// such as controllers or API controllers (unless you want to 
            /// change the defaults), as Unity allows resolving a concrete type 
            /// even if it was not previously registered.</remarks>
            public static void RegisterTypes(IUnityContainer container)
            {
                // NOTE: To load from web.config uncomment the line below. 
                // Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
                // container.LoadConfiguration();
    
                // TODO: Register your types here
                // container.RegisterType<IProductRepository, ProductRepository>();
                container.RegisterType<IStudentService,StudentService>();
                container.RegisterType<IStudentRepository, StudentRepository>();
            }
        }
    }
  34. Notice line numbers 43 and 44.
  35. Now let’s press F5 and see the result.DIAdd
  36. Let’s see the same result for Get.Request1Response
  37. 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>
  38. If we add a debugger on StudentController constructor, and go to immediate window, and write this._service, we will get {StudentApp.Service.StudentService}
    __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:

  1. Reduces class coupling
  2. Code reuse

There are several other containers available as well.

  1. spring.Net
  2. StructureMap
  3. 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.

Original Article by Santosh

Advertisements
Categories: Architecture
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: