Dependency Injection in ASP.NET Classes for TDD

Introduction 

 
This blog explains how to manage tightly coupled C# classes and make them loosely coupled. In ASP.NET classes, there is not a built-in library like Unity or Autofac.
 

What’s the problem with plain C# classes?

 
The reason for that is that in MVC or Web API Controller, objects are created via IHttpControllerActivator interface, which is inherited by a class. In Unity library IDependencyResolver is the user, which is kind of a ServiceLocator anti-pattern. Therefore, objects of controllers are created without manual intervention
 
This IHttpControllerActivator lies in the API pipeline to instantiate controllers.
 
Now when we develop C# classes and the code becomes too big and complicated, it automatically becomes tightly coupled, which makes TDD harder and next to impossible because there is no way to inject mock/test classes instead of the actual DB or DLL library classes
 

How to solve it?

 
Dependency Injection In ASP.NET Classes For TDD
 
We can create a ServiceLocator anti-pattern in plain old .net classes for DI purpose. Instead of directly creating object of third party DLL library we can simply register those in ServiceLocator anti-pattern and then resolve the dependency within the scope of the anti-pattern.
  1. namespace DIviaReflection  
  2. {  
  3.     public class ServiceLocator  
  4.     {  
  5.         // Key = interface  
  6.         // Value = concrete type that implements the Key interface  
  7.         private static readonly Dictionary<Type, ServiceTypeContainer> types;  
  8.   
  9.         // used for locking, especially when creating objects using reflection  
  10.         private static object syncObject = new object();  
  11.   
  12.                 static ServiceLocator()  
  13.         {  
  14.             types = new Dictionary<Type, ServiceTypeContainer>();  
  15.             Register<IDependency>(typeof(Dependency));  
  16.         }  
  17.   
  18.         public static T Resolve<T>()  
  19.         {  
  20.   
  21.             ServiceTypeContainer typeContainer = types[typeof(T)];  
  22.             T returnObj;  
  23.   
  24.             if (typeContainer.Initializer == null)  
  25.             {  
  26.                 // CreateInstance uses a static cache that is not thread-safe  
  27.                 // We could change the lock to on typeContainer if this becomes a bottleneck  
  28.                 lock (syncObject)  
  29.                 {  
  30.                     returnObj = (T)Activator.CreateInstance(typeContainer.ServiceType);  
  31.                 }  
  32.             }  
  33.             else  
  34.             {  
  35.                 returnObj = (T)typeContainer.Initializer();  
  36.             }  
  37.   
  38.             return returnObj;  
  39.         }  
  40.   
  41.         public static void Register<T>(Type objT)  
  42.         {  
  43.             Register<T>(objT, null);  
  44.         }  
  45.   
  46.         public static void Register<T>(Type objT, ServiceInitializer initializer)  
  47.         {  
  48.             types.Add(typeof(T), new ServiceTypeContainer(objT, initializer));  
  49.         }  
  50.     }  
  51.   
  52.     public class ServiceTypeContainer  
  53.     {  
  54.         public Type ServiceType  
  55.         {  
  56.             get;  
  57.             private set;  
  58.         }  
  59.   
  60.         public ServiceInitializer Initializer  
  61.         {  
  62.             get;  
  63.             private set;  
  64.         }  
  65.   
  66.         public ServiceTypeContainer(Type serviceType, ServiceInitializer initializer)  
  67.         {  
  68.             ServiceType = serviceType;  
  69.             Initializer = initializer;  
  70.         }  
  71.   
  72.     }  
  73.   
  74.     public delegate object ServiceInitializer();  
  75.   
  76. }  
There are two classes above one is used to register classes and another type of container.
 
Now instead of tightly coupled code you can register all third party DLL classes in anti-pattern and then use it like with the interface only.
 
As you can see, I have registered the Dependency class using IDependency type. Later. I will resolve it using IDependency only.
 

Practical Use

 
Below is a class ProductHistoryClass which has parameterized constructor that takes a custom type as an argument which is in fact a reference to a service or a DLL class calling another method.
  1. namespace DIviaReflection  
  2. {  
  3.     public class ProductHistoryClass  
  4.     {  
  5.         private IDependency dependency;  
  6.   
  7.         public ProductHistoryClass()  
  8.         {  
  9.   
  10.         }  
  11.   
  12.         public ProductHistoryClass(IDependency _dependency)  
  13.         {  
  14.             dependency = _dependency;  
  15.         }  
  16.   
  17.         public int FindProductHistory()  
  18.         {  
  19.             return dependency.FindProductHistory();  
  20.         }  
  21.     }  
  22. }   
Below are our dependency Interface and class:
  1. namespace DIviaReflection  
  2. {  
  3.     public interface IDependency  
  4.     {  
  5.         int FindProductHistory();  
  6.     }  
  7.     public class Dependency : IDependency  
  8.     {  
  9.         public Dependency()  
  10.         {  
  11.   
  12.         }  
  13.   
  14.         public int FindProductHistory()  
  15.         {  
  16.             return 1;  
  17.         }  
  18.     }  
  19. }  
I have kept declaration and definition simple to understand.
 
Now, in the old days we would create an object of Dependencyclass and then pass the object into a constructor calling ProductHistoryClass, which makes our classes tightly coupled and difficult to modify in the future. So how do we make use of anti-pattern here? Don’t worry I got it covered.
 
In you calling class, you can do the following:
  1. public static void WithParam()  
  2.         {  
  3.             ProductHistoryClass prdCls = (ProductHistoryClass)Activator.CreateInstance(classType,ServiceLocator.Resolve<IDependency>());  
  4.             int res = prdCls.FindProductHistory();  
  5.         }  
Here, I have used reflection to create an object or ProductHistoryClass and ServiceLocator to resolve our dependency. Just by these simple lines of code, we are able to inject dependency in plain old c# classes. Now I would like you guys to experiment with this.
 
That's it for this blog! Hold tight until I write the next one...
 
If you enjoyed this blog, then please like it and leave a comment. Thank you!