Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

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

0.00/5 (No votes)
15 Aug 2017 1  
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.

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.

     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

[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.

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.

    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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here