Basics of Dependency Injection Pattern : )

The idea of the Dependency Injection Pattern is to write easily replaceable and maintainable code.
The same idea is applied also in the ASP.NET MVC:

ASP.NET MVC (Model – View – Controller) –
  • Model – a class for representation of the DB data, which is also used for transporting the data to the View, which will visualize it in an HTML web page.

In the example our DB Table will be called Users and will contain the fields from the class User as columns. The Rolefields is a bit field.

    • Example:
    public class User
    {
        public string Email { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Password { get; set; }

        public string FullName()
        {
            return string.Format("{0} {1}", this.FirstName, this.LastName).Trim();
        }

        public Role Role { get; set; }

        public string BadgeId { get; set; }

        public bool IsEmailSent { get; set; }

    }

  • Problem – In the HTML web page we don’t need to show all of the information, which we store in the DB(for example we don’t want to show the BadgeId) and we will often need to add a boolean flag, which we won’t want to store in the DB(Like Remember Me option when Log in). That means we are transferring unnecessary data to our View.
    • View – HTML page. It accepts one of our registered Model classes and takes the data from it to create HTML elements so it will be displayed to the user.
    • Example:
 
@model List<Web.Models.User>
@{
    Layout = Web.Common.Constants.WebConstants.LAYOUT_RELATIVE_LOCATION;
    ViewBag.Title = "Users";
}
@foreach(var user in users)
{
    <i class="icon-user">@user.Email - @user.FullName </i>
}

    • Problem

– our problem is that if we change the Model class(which represents our data stored in the DB) we will have to change the View again.

 

  • Controller – a class, which extends the class Controller in .NET. We put all the visualization logic, sorting, searching etc. It contains the so called “Business logic” (logic, which is applied to the data so the data can mean something to the user – for example some kind of calculations, dividend and other specific logic for the app).

 

    • Example
 
        public ActionResult Index()
        {
            var users = dbContext.Users.GetAll
.Where(x => x.Role == Role.Visitor && x.Age < 35 && x.FirstName.Contains("John").ToList();

            return View(users);
        }

  • Problem – if tomorrow we decide to change the logic in the controller(for example stop displaying users with Admin role and only show users with Visitor role), we should do it easily at one place, not in each controller and we should not touch the View connected with the controller. So the answer to our problem is to create a place from which the controller will get the data and serve it to the View in the needed form from the View.
As you can see the MVC model gives us a lot freedom to work with the data but may be not so complete. So if lets make a conclusion about the MVC with out software design approach:
  1. We cannot easily change the project logic without changing code on many places.
  2. We will often load unnecessary data
  3. The work with simple fields, which should not be stored in the DB will be complicated
  4. There are many dependencies between the classes in the project.
So each one of these problems could cause us a lot of headache.
What are the answers? 
Basically the answer to all problems is one. We need to create weak dependency between the components of our project, separate the business logic in a separate layer, so it can be easily changed and create presentation models, which will transfer only the needed data by the views.
  1. DI container – to achieve weak dependency
  2. Separate Library Project (Service layer pattern) called BL (from Business Logic) which contains Interfaces and Realizations so we can isolate the BL.
  3. The Models folder of the MVC will be populated with ViewModel classes (simple classes containing only the needed data to be presented on the HTML page). We will have to map our ViewModel classes with our Db classes.
So to get the complete weak dependency, the thing which I met was the Dependency Injection pattern.
Using this pattern the dependencies(the classes which you want to use in your other class) are injected by two ways:
  • in the constructor of the new class – MyNewClass(AccountClass account, UserClass user)
  • using a property – this is specifically for .NET

Here is an example:

 public class UsersController : Controller
    {

        IAccountService accountService;
       
        public UsersController(IAccountService _accountService)
        {
            accountService = _accountService;
        }

        public ActionResult Index()
        {
           var users = accountService.GetAll
.Where(x => x.Role == Role.Visitor && x.Age < 35 && x.FirstName.Contains("John")
                 .ToList();

            return View(users);
        }
}

As you can see in the constructor we receive an instance of an interface called Account service, from which we take the needed data. Here is the declared interface:

 public interface IAccountService
    {
        bool ValidateLogIn(string email, string password, out User user);

        User CurrentUser { get; set; }

        bool ChangePassword(User user, string newPassword);

        List<user> GetUsers(Role role);
    }

As we know the interface is only used for declaration and does not have any functionality in it. So we have to declare somewhere a class which extends the interface in example AccountService.class which extends IAccountService.interface. Here it is:

 public class AccountService : IAccountService
    {
        public bool ValidateLogIn(string email, string password, out User user)
        {
            user = this.GetAllNonDeleted().FirstOrDefault(u => u.Email == email);

            if (user == null)
            {
                return false;
            }
            ....
         }
.....
}

After we have the realization of the methods from our interface we should make the connection between the controller and the service we inject. So we must say in a place within our app: “When the controllers need IAccountService realization please inject AccountService.class”.

You can have multiple ways to realize that connection. You can use a Factroy.

You can make your own mapper using a Dictionary, which knows the connections between the interfaces and the classes.

But basically in .NET you can use a so called Dependency injector which is a separate library where you declare your interfaces and classes and the library handles the correct instantiation of the classes. (So you don’t have to handle memory management.)

In the next part of this lesson I will review the Ninject dependency injector for .NET.


History:

  1. Current
  2. Dependency Injection Framework (Ninject) and .NET

You may also like...