Introduction
This article explains the use of Unity Framework for Dependency Injection and takes a different approach for resolving dependency amongst classes and interfaces. Advantages of Dependency injection are simplified code and generate dependent object instances. We might be aware of registering types using C# but there is another approach as well. We can use the Configuration files to declare and register types and then Resolve in within our code. This article will help you understand it in a practical and clean approach. This article also covers a scenario of switching different Unity Configuration files based on requirements from the Business.
Background
Before this article, it would be more beneficial that you refer to Microsoft Unity and How to use Unity in ASP.NET MVC Framework articles to get a better understanding about how Unity works and how it can solve most of our problems making life easier.
Business Requirements
I'd like to share the reason for starting to work with Unity. There was a special requirement that came up from the business that they wish to take off the existing database and switch to a new database which had no comparable schema. Hence, all developers had to write all the repositories again with respect to new database. But if the Repository methods were changed, there were high changes the Business logic or the references needed to be updated. So my tech leads came up with an idea of using Unity Framework for Dependency Injection and allowing the flexibility to switch between the old and new repositories. They wanted to test the new repositories but didn't want to remove old repositories until they find everything in a good shape. Further part will explain how I tackled this requirement using Unity.
Using the Code
Before starting with coding, we need to get Unity Framework Package from Nuget Package manager. To grab the package, go to Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution.
For the demo, I've created a project where we shall be using different courier repositories and fetch rates. There is an Interface ICourierRepository
which is being Implemented by UspsRepository
and FedexRepository
. Basically, the application will select Repository based on which 'Type
' we register in Web.Config
or Unity.Config
files. The first part of the project is to create a Unity Section in Web.Config file.
We created a new section named 'Unity
' which in return provides the file name for Unity. In the image, configSource = "NewRepositoryUnity.config"
says that there is a some file which also needs to be checked. The code will look into NewRepositoryUnity.config
.
Below is the code for declaring and resolving types using Web.Config file. We need to setup the Unity Container before using it. It involves registering the types and in the first four lines, we are setting up aliases variable types that needed to be used and injected. In the type
attribute, we need to mention the namespace
and Assembly
of the type for proper mapping. Aliases as used to refer to any type instead of mentioning its Namespace
and Assembly
.
Next part is declaring Unity Container. Here, I'm using CourierContainer
as my container name. Container name is used in cases when we have multiple containers and I wish to Resolve a particular container. In this container section, we register all the types with Unity along with explicitly mentioning its Type
, mapTo
and name
. We register the Interfaces with all classes implementing that interface and providing them with names defined in the Aliases
. We also register our Business Class CourierBusiness
but in a different way. We are using parameterized constructor for Dependency Injection, so we need to mention the type in the config file. Here we need to make sure that the name of the parameter in the construction signature matches the name in the config file (in this example, it's courierRepository
). We are registering our Business Class twice because we wish to use either of the two Repositories, i.e., Usps or Fedex and I do not wish to explicitly NEW
up the instances everytime. Hence, we need separate Register tags for each repository I wish to use.
namespace UnityFrameworkExample.Business
{
public class CourierBusinessClass
{
private ICourierRepository _courierRepostitory;
public CourierBusinessClass(ICourierRepository courierRepository)
{
_courierRepostitory = courierRepository;
}
public string GetLatestPrices()
{
var message = _courierRepostitory.GetCourierPrices();
return message;
}
}
}
How It Works
IUnityContainer container = new UnityContainer();
container.LoadConfiguration("CourierContainer");
Initially, we need to create an instance of UnityContainer
and then load the required Unity Configuration (in this case, its CourierContainer
). If all our assemblies and namespace are correct, we will receive no errors at this step.
var uspsInstance = container.Resolve<CourierBusinessClass>("UspsCourier");
ViewBag.uspsCourierPrice = uspsInstance.GetLatestPrices();
var fedexInstance = container.Resolve<CourierBusinessClass>("FedexCourier");
ViewBag.fedexCourierPrice = fedexInstance.GetLatestPrices();
Now, we need to resolve the class we need to use. Here, we are resolving our CourierBusinessClass
. We do not need to create a New
Instance of the class nor we need to pass any parameter in the constructor while declaration, Unity Framework does it for us automatically. Now based on our requirement, whether we need to use Usps
or Fedex repository
, we need to pass string
while resolving. Unity Framework will try to match the string
with the name in the Config file and if the match is found, it will create the instance of that type. For example, here we are passing UspsCourier
on the first line. Unity Framework will look for that name in Config file with Type of "CourierBusinessClass
". Here we go, it got a match. Unity will realize that it uses a parameterized constructor with the type of ICourierRepository
. But we have dependency name declared which will help Unity to point out to appropriate type. Here dependency name is UspsCourierRepository
. Unity will look for aliases UspsCourierRepository
and if a match is found, it will create an instance of UspsCourierRepository
Class". Finally, when GetLatestPrices()
method is executed, it will point out to method in UspsCourierRepository
and return results accordingly.
Switching Between Multiple Unity Config Files
As I previously explained the business problem, we needed multiple repositories which can be switched as and when needed. That can be done by just changing the name of the file in Web.Config file. So I created a new Unity Config file and mapped all the types to old repositories. Below is the screenshot of config file with old repositories.
Points of Interest
I was really amazed when I understood the concept of Dependency Injection using Unity and how it can simplify the code. The best part is that the documentation for Unity is so simple that it helped me understand it and come up with this concept. Even we are able to achieve Inversion of Control(IoC) using Unity making sure that Business layer does not have to do anything with 'Newing' up the repository instances.