Unity Application Block is a lightweight dependency injection container from Microsoft Patterns & Practices. This article is intended to show how quickly and easily integrate Unity with your code.
Start by downloading and installing Unity. The current version, 2.1, consist of 5 libraries:
- Microsoft.Practices.ServiceLocation.dll
- Microsoft.Pracitces.Unity.dll
- Microsoft.Practices.Unity.Configuration.dll
- Microsoft.Practices.Unity.Interception.dll
- Microsoft.Practices.Unity.Interception.Configuration.dll
There are at least two ways to define type bindings in Unity – declaratively in a *.xml file and programmatically in a C# code.
The nice thing is that you can combine both approaches in desired order so for example you first create few mappings programmatically and then load the static configuration which can possibly override some of mappings.
Now create a new application (Windows or web) and add references to unity libraries (first 3 will do as this tutorial doesn’t cover interceptions).
Anyway, first go to the application *.config file (app.config for Windows applications, web.config for web apps) and inform the runtime that you are going to configure unity using the *.xml file:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity configSource="Configuration\unity.config"/>
</configuration>
As you can see I am delegating the Unity configuration to a separate file, Configuration\unity.config. This is a good practice as you have all the IoC configuration in a single place which doesn’t interfere with any other application settings.
For this tutorial, create a service specification and two implementations:
public interface ICustomService
{
string BusinessOperation();
}
public class CustomServiceImpl : ICustomService
{
#region ICustomService Members
public string BusinessOperation()
{
return "foo";
}
#endregion
}
public class CustomServiceImpl2 : ICustomService
{
#region ICustomService Members
public string BusinessOperation()
{
return "bar";
}
#endregion
}
We are going to provide a static mapping in the *.xml file, Configuraton\unity.config:
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="ConsoleApplication30.Logic.ICustomService, ConsoleApplication30"
mapTo="ConsoleApplication30.Logic.CustomServiceImpl, ConsoleApplication30" />
</container>
</unity>
As you can see, the interface ICustomService is mapped to CustomServiceImpl.
The remaining part is to configure the service locator:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.Practices.ServiceLocation;
using ConsoleApplication30.Logic;
namespace ConsoleApplication30
{
class Program
{
static void Main( string[] args )
{
UnityServiceLocator locator = new UnityServiceLocator( CreateConfiguredUnityContainer() );
ServiceLocator.SetLocatorProvider( () => locator );
}
private static IUnityContainer CreateConfiguredUnityContainer()
{
IUnityContainer container = new UnityContainer();
// (optional) provide default mappings programmatically
container.RegisterType<ICustomService, CustomServiceImpl2>();
// (optional) load static config from the *.xml file
container.LoadConfiguration();
return container;
}
}
}
As you can see the locator is created over a container which shows how to perform dynamic and static configuration.
Remember that Unity, as most of IoC containers, allows to reregister services – if you provide two or more mappings of the same service type to a concrete implementation, the last registered implementation is always used when you resolve the service (which is reasonable). In this tutorial I am creating a mapping in code from ICustomService to CustomServiceImpl2.
From now on you can ask the service locator services and consume them:
ICustomService service = ServiceLocator.Current.GetInstance<ICustomService>();
var foo = service.BusinessOperation();
It couldn’t be easier. Personally, when I am free to pick an IoC container, I often pick Unity – it’s reliable, simple and lightweight.
A quick quiz: in the example, I am mapping the implementation to CustomServiceImpl2 and in the next line I am loading the configuration from the *.xml file which in turn maps the implementation to CustomServiceImpl then what would be the result of resolving the service type?