The Unity Application Block Feb 2008 CTP (from now on called Unity) is released on www.codeplex.com/unity. It's a lightweight dependency injection container with support for constructor, property and method call injection.
To get people started with this, I created a small example. Actually I ported my Dependency Injection with Spring.NET example from some posts ago to this release of Unity.
This sample shows how a class can get an reference to another class through its constructor.
Hit this link to download this example (VS2008!)
Let assume that ClassA needs a reference to ClassB. But ... not always to ClassB. Sometimes, for testing purposes, you would like to have another Class (called ClassB2 in this example) being giving to the constructor. Yeah, once again .... the loose coupling pattern, very usefull from the point-of-view of unittests.
So ClassA Looks like this :
public class ClassA
{
IClassB _refToB;
public ClassA(IClassB b)
{
Console.WriteLine("Class A constructed!");
_refToB = b;
}
public void Test()
{
_refToB.DoSomething();
}
}
Of course ClassB2 would need to implement the same interface as ClassB does otherwise the compiler is not satisfied. Note that the contructor for ClassA gets a reference to a class which implements this interface called IClassB
IClassB (the Interface for ClassB and ClassB2) looks like this :
public interface IClassB
{
void DoSomething();
}
Concrete implementation of ClassB :
class ClassB : IClassB
{
public ClassB()
{
Console.WriteLine("Class B constructed!");
}
public void DoSomething()
{
Console.WriteLine("Class B did something");
}
}
Concrete implementation of ClassB2 :
class ClassB2 : IClassB
{
public ClassB2()
{
Console.WriteLine("Class B2 constructed!");
}
public void DoSomething()
{
Console.WriteLine("Class B2 did something");
}
}
Ok, these are normal classes, nothing special. If we want to use them, we instantiate them with the new operator. First instantiate ClassB (or ClassB2) than instantiate ClassA giving it the freshly created ClassB (or ClassB2) in the constructor. Not ! This is too tighly coupled !
With a depency injector container (like Unity) we do not explicitly program the instantiations with the new operator. The container will do this for us. Al we have to do is : ask the container which object we want. If we ask for ClassA, the container will see that the constructor must have an instantiation of a class that implements IClassB and such a class will be instantiated for us and been given to this constructor.
Of course the container must know what concrete class (ClassB or ClassB2) it must instantiate. This is done by first mapping the Interface type to the concrete type, either by code or by configuration.
By Code :
IUnityContainer container = new UnityContainer();
container.Register(typeof(IClassB), typeof(ClassB2));
This code results in the creating of the container. Thereafter the IClassB interface type is mapped to the concrete ClassB2. From now on, if we want the have ClassA instantiated we just ask the container to get a reference by specifying the type in the generic Get method of the container.
ClassA a1;
a1 = container.Get<ClassA>();
a1.Test();
So this method will lookup (through reflection) if other instantiations are needed (= dependent) and detects that it needs a class of type IClassB in the constructor. Because we already mapped ClassB2 to this interface the container is able to know that he needs to instantiate ClassB2 and thereafter needs to instantiate ClassA with the reference to ClassB2.
Result :
Class B2 constructed!
Class A constructed!
Class B2 did something
By Configuration :
In the previous way the choice of wich implementation of the interface to use is still hardcoded in the program. To be really loose coupled we need to have this decision written down in the configuration. Unity also supports this.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="unity"
type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<containers>
<container>
<types>
<type type="TestUnity.IClassB,TestUnity"
mapTo="TestUnity.ClassB2,TestUnity" />
</types>
</container>
</containers>
</unity>
</configuration>
In this configuration the mapping between IClassB an ClassB2 (or ClassB) is clearly specified. To read this configuration we need to use the ConfigurationManager like this :
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section;
section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.GetConfigCommand().Configure(container);
The rest of the code remains the same.
Bottom line : The container shields the developer away from that awfull new operater and gives him/her the needed objects based on a simple configuration.
But ... there's more (lots of ...)
For example : You can even configure the container to use singletons when instantiating the classes by setting the lifetime attribute. By default the Unity container will not use singletons unless you specify this. Like this :
<type type="TestUnity.ClassA,TestUnity"
mapTo="TestUnity.ClassA,TestUnity"
lifetime="Singleton"
/>
Result : when calling this code ....
ClassA a1;
a1 = container.Get<ClassA>();
a1.Test();
ClassA a2;
a2 = container.Get<ClassA>();
a2.Test();
... the constructor of ClassA and the constructor of ClassB2 (or ClassB) will only be executed once and a1 and a2 will point to the same instantiation without the need to write our own singleton logic.
One advice about the CTP : clearly the documantation is not in syc with this release. Please follow the discussions about this on http://www.codeplex.com/unity/Thread/List.aspx