Dependency Injection in ASP.NET

Reference: By Adam Freeman – Pro ASP .NET MVC 4 4th Edition

One of most important features of the MVC pattern is that it enables separation of concerns. We want the components in our application to be as independent as possible and to have as few interdependencies as we can manage. In ideal situation, each component knows nothing about any other component and only deals with other areas of the application through abstract interfaces. This is known as loose coupling, and it makes testing and modifying our application easier.

A simple example will help put things in context. If we are writing a component called MyEmailSender that will send e-mails, we would implement an interface that defines all of the public functions required to send an e-mail, which we would call IEmailSender. Any other component of our application that needs to send an e-mail—let’s say a password reset helper called PasswordResetHelper, can then send an e-mail by referring only to the methods in the interface. There is no direct dependency between PasswordResetHelper and MyEmailSender:

By thus, we could replace MyEmailSender with another e-mail provider or even use a mock implementation for testing purposes.

Using Dependency Injection

Interfaces help us decouple components, but we still face a problem—C# doesn’t provide a built-in way to easily create objects that implement interfaces, except to create an instance of the concrete component:

public class PasswordResetHelper {
    public void ResetPassword() {
        IEmailSender mySender = new MyEmailSender();
        //...call interface methods to configure e-mail details...
        mySender.SendEmail();
    }
}

We are only part of the way to loosely coupled components—the PasswordResetHelper class is configuring and sending e-mails through the IEmailSender interface, but to create an object that implements that interface, it had to create an instance of MyEmailSender. We have made things worse—now PasswordResetHelper depends on IEmailSender and MyEmailSender:

What we need is a way to obtain objects that implement a given interface without having to create the implementing object directly. The solution to this problem is called dependency injection (DI), also known as Inversion of Control (IoC).

DI is a design pattern that completes the loose coupling we started by adding the IEmailSender interface to our simple example. There are two parts to the DI pattern. The first is that we remove any dependencies on concrete classes from our component—in this case PasswordResetHelper. We do this by passing implementations of the required interfaces to the class constructor:

public class PasswordResetHelper
{
    private IEmailSender emailSender;
    public PasswordResetHelper(IEmailSender emailSenderParam)
    {
        emailSender = emailSenderParam;
    }
    public void ResetPassword()
    {
        // ...call interface methods to configure e-mail details...
        emailSender.SendEmail();
    }
}

We have broken the dependency between PasswordResetHelper and MyEmailSender—the PasswordResetHelper constructor demands an object that implements the IEmailSender interface, but it does not know, or care, what the object is and is no longer responsible for creating it. The dependencies are injected into the PasswordResetHelper at runtime—that is to say, an instance of some class that implements the IEmailSender interface will be created and passed to the PasswordResetHelper constructor during instantiation. There is no compile-time dependency between PasswordResetHelper and any class that implements the interfaces it depends on.

Because the dependencies are dealt with at runtime, we can decide which interface implementations are going to be used when we run the application—we can choose between different e-mail providers, or inject a mocked implementation for testing.

Here is an MVC-Specific DI Example:

public interface IMembersRepository
{
    void AddMember(Member member);
    Member FetchByLoginName(string loginName);
    void SubmitChanges();
}
public class MembersRepository : IMembersRepository
{
    public void AddMember(Member member)
    {
        /* Implement me */
    }
    public Member FetchByLoginName(string loginName)
    {
        /* Implement me */
    }
    public void SubmitChanges()
    {
        /* Implement me */
    }
}

And in controller:

public class AdminController : Controller
{
    IMembersRepository membersRepository;
    public AdminController(IMembersRepository repositoryParam)
    {
        membersRepository = repositoryParam;
    }
    public ActionResult ChangeLoginName(string oldLoginParam, string newLoginParam)
    {
        Member member = membersRepository.FetchByLoginName(oldLoginParam);
        member.LoginName = newLoginParam;
        membersRepository.SubmitChanges();
        // ... now render some view
        return View();
    }
}

The AdminController class demands an implementation of the IMembersRepository interface as a constructor parameter—this will be injected at runtime, allowing AdminController to operate on an instance of a class that implements the interface without being coupled to that implementation.

Using a Dependency Injection Container

We have resolved our dependency issue—we are going to inject our dependencies into the constructors of our classes at runtime. But we still have one more issue to resolve—how do we instantiate the concrete implementation of interfaces without creating dependencies somewhere else in our application?

The answer is a dependency injection container, also known as an IoC container. This is a component that acts as a broker between the dependencies that a class like PasswordResetHelper demands and the concrete implementation of those dependencies, such as MyEmailSender.

We register the set of interfaces or abstract types that our application uses with the DI container, and tell it which concrete classes should be instantiated to satisfy dependencies. So, we would register the IEmailSender interface with the container and specify that an instance of MyEmailSender should be created whenever an implementation of IEmailSender is required. Whenever we need an IEmailSender, such as to create an instance of PasswordResetHelper, we go to the DI container and are given an implementation of the class we registered as the default concrete implementation of that interface—in this case, MyEmailSender.

We do not need to create the DI container ourselves—there are some great open source and freely licensed implementations available. The one we like is called Ninject, which will be introduced in the next post.

 

3 comments

  1. Hubert says:

    Great post. I ‘m confronting a couple of these problems.

  2. Thomas says:

    Hi , I do consider this is a superb website. I stumbled upon it on Yahoo , I
    ‘ll come back once again.

  3. The article has actually peaks my interest.
    Iwill bookmark your website and keep checking for new info.

Leave a Reply

Your email address will not be published. Required fields are marked *