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()
{
var builder = new ContainerBuilder();
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);
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolve<wbr />r(container);
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.