Click here to Skip to main content
15,884,099 members
Articles / Programming Languages / C#

Dependency Injection in ASP.NET Web API using Autofac via Attributes and Reflection

Rate me:
Please Sign up or sign in to vote.
3.05/5 (8 votes)
15 Aug 2017CPOL2 min read 23.4K   2   6
Resolving Dependencies via Attributes and Reflection

Introduction

In this Article we will figure out how to create a Dependency Injection Attribute and use it across the application and eradicate clutter code. 

I will be using AutoFac WebApi Container as my Dependency Injection Resolver.

The Problem

When we start using any Container for resolving the Dependencies in the Project. We write a lot of clutter code as shown below for registering our dependencies.

C#
builder.RegisterType<<wbr />EmployeeManager>().As<<wbr />IEmployeeManager>();
builder.RegisterType<<wbr />CustomerManager>().As<<wbr />ICustomerManager>();
builder.RegisterType<<wbr />EmployeeRepository>().As<<wbr />IEmployeeRepository>();
builder.RegisterType<<wbr />CustomerRepository>().As<<wbr />ICustomerRepository>();

                                   ...

                                   ...

builder.RegisterType<<wbr />CustomerManager>().As<<wbr />ICustomerManager>();
builder.RegisterType<<wbr />EmployeeRepository>().As<<wbr />IEmployeeRepository>();
builder.RegisterType<<wbr />CustomerRepository>().As<<wbr />ICustomerRepository>();

As the Size of the Project grows the no of lines in the Dependency Builder grows.

There are multiple problems associated with this.

1. Every time you want to add dependencies you need to come to the Dependency class and add the relevant dependencies.
2.If the developer during merging  the code can over write out some of the dependencies.
3.The Class keeps growing and at some point of time you would feel its not maintainable.
4.It would violate Open/Closed Principle of SOLID principles

Solution

We will now see how we could solve this clutter code by Attribute and Reflection.

Step 1

We will Create a Common Library in the Project and Create an InjectableAttribute class which Inherits Attribute class under System namespace.

C#
     using System; 
     namespace AutoFacCommon 
     { 
        public class InjectableAttribute : Attribute
        { 
   
        } 
     }

I have used "InjectableAttribute" as name since Angular2 has a Dependency Injection with name Injectable. Wanted to synchronize both Client and Server

Step 2

Now since we have created the Injectable Attribute. We need to decorate the class with this Attribute

C#
[Injectable]
public class EmployeeManager : IEmployeeManager
{
    private readonly IEmployeeRepository _employeeRepository;

    public EmployeeManager(<wbr />IEmployeeRepository employeeRepository)
    {
        _employeeRepository = employeeRepository;
    }

    public IList<Employee> GetAllEmployess()
    {
        var employeeData = _employeeRepository.<wbr />GetAllEmployees();
        var employeeList = new List<Employee>();
        foreach (var employee in employeeData)
        {
            var employ = new Employee();
            employ.EmployeeDesignation = employee.EmployeeDesignation;
            employ.EmployeeId = employee.EmployeeId;
            employ.EmployeeName = employee.EmployeeName;
            employeeList.Add(employ);
        }
        return employeeList;
    }
}

Note: When you see the [Injectable] Attribute decorated on the class. It essentially means that this class is ready to be injected. Where ever this class is necessary.

Step 3

Now lets inject this class in the WebApi Controller as shown below.

C#
public class EmployeeController : ApiController
{
    private readonly IEmployeeManager _employeeManager;

    public EmployeeController(<wbr />IEmployeeManager employeeManager)
    {
        _employeeManager = employeeManager;
    }

    [AllowAnonymous]
    [ResponseType(typeof(Employee)<wbr />)]
    public IHttpActionResult GetEmployees()
    {
        var employeeData = _employeeManager.<wbr />GetAllEmployess();
        return Ok(employeeData);
    }
}

When you run the above piece of code from swagger or postman will it work?. No wait did we say CLR to resolve the dependencies. Nope so far we haven't done anything as such.

Lets do that now.

Step 4

We need to have Autofac.WebApi2 and AutoFac. You can download the same from the Nuget Package Manager

We will build the Static AutoFacDependencyBuilder class as shown below.

C#
    public static class AutofacDependecyBuilder
    {

        public static void DependencyBuilder()
        {
            // Create the builder with which components/services are registered.
            var builder = new ContainerBuilder();

            // Register your Web API controllers.
            builder.<wbr />RegisterApiControllers(<wbr />Assembly.GetExecutingAssembly(<wbr />));

            builder.RegisterAssemblyTypes(<wbr />AppDomain.CurrentDomain.<wbr />GetAssemblies())
                                      .Where(t => t.GetCustomAttribute<<wbr />InjectableAttribute>() != null)
                                      .AsImplementedInterfaces()
                                      .InstancePerRequest();

            builder.<wbr />RegisterWebApiFilterProvider(<wbr />GlobalConfiguration.<wbr />Configuration);

            //Build the Container
            var container = builder.Build();

            //Create the Dependency Resolver
            var resolver = new AutofacWebApiDependencyResolve<wbr />r(container);

            //Configuring WebApi with Dependency Resolver
            GlobalConfiguration.<wbr />Configuration.<wbr />DependencyResolver = resolver;

        }

    }

The above code which is bold is the piece of puzzle which will bring all the parts together.

This code will  load all the assemblies once when the project is loaded for the first time. It will using reflection get all the custom attributes and create instance per request. In our case it is Injectable custom Attribute.

Step 5

Alright after all the hard work we need to initialize the AutoFac dependency Builder Class in the Global.asax or App.Start file as shown below.

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        GlobalConfiguration.Configure(<wbr />WebApiConfig.Register);
        AutofacDependecyBuilder.<wbr />DependencyBuilder();
    }
}

Now we could say that it will work beautifully.

If you do not want to go through all the hard work. You can below link of the repository. Its should help you get started.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Tavant Technologies
India India
Crazy Software Developer and a passionate lover of Amour.

My only aim as a developer is to write more cleaner, more maintainable and extensible code.

Comments and Discussions

 
Questiongetting exception Pin
titu-167031910-Jun-19 19:18
titu-167031910-Jun-19 19:18 
GeneralMy vote of 2 Pin
srinivas kollipara29-Nov-17 6:15
srinivas kollipara29-Nov-17 6:15 
GeneralRe: My vote of 2 Pin
Vaibhav M Nalwad3-Dec-17 19:33
professionalVaibhav M Nalwad3-Dec-17 19:33 
QuestionHow to do the same with unity DI Pin
Mou_kol15-Aug-17 22:40
Mou_kol15-Aug-17 22:40 
AnswerRe: How to do the same with unity DI Pin
Vaibhav M Nalwad15-Aug-17 23:28
professionalVaibhav M Nalwad15-Aug-17 23:28 
GeneralRe: How to do the same with unity DI Pin
Mou_kol16-Aug-17 22:31
Mou_kol16-Aug-17 22:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.