Sunday, March 31, 2013

Managing Dependency Injection in C# with Autofac


Dependency Injection in software engineering is a specific form of inversion of control. Conventionally, when an object needs access to a particular service, this object takes responsibility for access to this service.

Commonly, an object receives a link to the service location or appeals to some "service locator" and requests a reference to the implementation of a specific type of service. When implementing Dependency Injection, object simply provides a property that is able to keep a reference to the type of service, and when the object is created, a reference to the implementation of the desired type of service is automatically inserted into the property (field).

Dependency Injection is more flexible because it becomes easier to create alternative implementations of this type of service, and then specify exactly which implementation should be used, for example in the configuration file, with no changes in the objects that use this service. This is especially useful in unit testing.

C# Dependency Injection with Autofac

Today I'll show a simple example of managing dependency injection with Autofac. Autofac is an Inversion of Control Container for .NET. It helps to manage dependencies between classes so that applications stay easy to change as they grow in size and complexity. This achieved by treating regular .NET classes as components. You can download Autofac from here.

Our example application is a console program that checks a list of employees and notifies which of them are experts (work experience more than 10 years).

Here is our Employee class:

class Employee
{
    public string Name { get; set; }
    public string Position { get; set; }
    public int Experience { get; set; }
}
EmployeeObserver class is the core of the application, its main purpose is to find employees that satisfy our condition - their work experiences is more than ten years.
class EmployeeObserver
{
    readonly IList<Employee> _employees;
    readonly IEmployeeNotifier _notifier;

    public EmployeeObserver(IList<Employee> employees, IEmployeeNotifier notifier)
    {
        _employees = employees;
        _notifier = notifier;
    }

    // find employees with more than 10 years of experience
    public void FindExperts()
    {
        var experts = _employees.Where(e => e.Experience > 10);

        foreach (var e in experts)
            _notifier.PrintExperts(e);
    }
} 

Now we need to create a Printer class which will be responsible for printing out messages to a TextStream. Printer will implement IPrinter interface.
interface IPrinter
{
    void PrintExperts(Employee employee);
}

class Printer : IPrinter
{
    private readonly TextWriter _textWriter;

    public Printer(TextWriter writer)
    {
        _textWriter = writer;
    }

    public void PrintExperts(Employee employee)
    {
        _textWriter.WriteLine("Employee {0} is an expert.", employee.Name);            
    }
}
Now all set for Dependency Injection. As you can see we can make Dependency Injection by hand, without Autofac:
var di = new EmployeeObserver(employees, new Printer(Console.Out));
di.FindExperts();
In fact this code looks very simple, but in real application with many layers and all kind of components configuring dependency injection by hand will become very complex. Dependency injection containers, such as Autofac, bring order to this world of chaos. Let's see how we use it:
ContainerBuilder autofac = new ContainerBuilder();
autofac.Register(o => new EmployeeObserver(o.Resolve<IList<Employee>>(), o.Resolve<IPrinter>()));
autofac.RegisterType<Printer>().As<IPrinter>();
autofac.RegisterInstance(employees).As<IList<Employee>>();
autofac.RegisterInstance(Console.Out).As<TextWriter>();
using (var container = autofac.Build())
{
    container.Resolve<EmployeeObserver>().FindExperts();
}
Autofac application output

May be on this particular example it's hard to see why this approach is better than configuring dependency injection by hand, but you should notice one important thing - with Autofac each component is configured independently of all the others, and this is what will make a big difference when your application become more complex.

Download the source code (Visual Studio 2012 project).

6 comments:

  1. Heh, "invasion of control" (first paragraph)? I think I like that better than "inversion of control." :)

    ReplyDelete
  2. Could you please share the whole code of the Autofac part?
    I did not really get what parts of the code you did not need to implement in this case.
    Thank you in advance.

    ReplyDelete
    Replies
    1. Tarek there is a link at the end of the article to the whole project. You're welcome to download it.
      Thank you!

      Delete
  3. Hi,

    I truly fail to see how this AutFac example will ever become more beneficial with scaling up. I have project with more than 500 business classes and several thousands of actions and method and try to imagine AutoFac code scaled up to my needs and I get instant migrane :-)

    Thanks for showing I do not want to deal with this things, though :-)

    ReplyDelete