This Microsoft Unity Tutorial will aim to make is easy for the uninitiated to work with Microsoft Unity. Unity is a dependency injection container. The best source for Unity remains the developer guide which is also available as a free eBook download. I will strongly recommend that you get a foundation on Inversion of Control(IoC) and Dependency Injection(DI) first.
As usual I will start with WHY followed by HOW.
BTW For the people who came here looking for Unity gaming engine, well Hello. You were maybe looking for this.
UPDATE: Well I thought that Unity was dead. Not so. It is back in active development and at the time of writing, version 5.8.6 is available as nuget package.
WHY
Well if you go through the posts I wrote on the IoC and DI, then you will have a good understanding how they help in writing good maintainable software. The reason for writing this Microsoft Unity tutorial is that there are not as many web resources on Unity as I would like. This of course has to do with the fact that there more popular DI containers like Castle Windsor. Unity is not that well known. But since I was working with Unity, I decided to write a small tutorial to make it easy for the new users to ramp up rapidly on Unity.
HOW
Unity can be used in many ways. This Microsoft Unity tutorial will show Unity in action via small code snippets.
There are two stages of using Unity.
1. Telling Unity how to create an object of a class which is implementing a particular interface. This stage is called “Registration”.
2. Telling Unity to create the object. This stage is called “Resolution”.
Unity authors have recommended that :
1. Registration of all the types should happen in a single method, typically at the start-up of the program.
2. The code should be decoupled from the injection container used. In simple terms it means that the Unity reference should appear in the method which does the registration and and in the main method where you might have to pass an instance of Unity container to the registering method. Rest of the code should be oblivious to the fact that Unity is getting used.
I will dig up my old Radio example again.
There will be as usual, the IBattery.cs
interface
namespace UnityDemo
{
public interface IBattery
{
bool SelfCheck();
int ChargeRemaining();
string Manufacturer();
string SerialNumber();
}
}
And the Battery.cs
implementing this interface.
namespace UnityDemo
{
public class Battery : IBattery
{
public bool SelfCheck()
{
return true;
}
public int ChargeRemaining()
{
return 70;
}
public string Manufacturer()
{
return "Wayne Enterprises";
}
public string SerialNumber()
{
return "123XXGDASJ2345";
}
}
}
We have the ITuner.cs
interface too
namespace UnityDemo
{
public interface ITuner
{
string Manufacturer();
int TunedFrequency();
bool SelfCheck();
string SerialNumber();
}
}
which is implemented by the Tuner.cs
namespace UnityDemo
{
public class Tuner : ITuner
{
public string Manufacturer()
{
return "Tesla Labs";
}
public int TunedFrequency()
{
return (int)99.8;
}
public bool SelfCheck()
{
return true;
}
public string SerialNumber()
{
return "23423HJSDFGJ234";
}
}
}
To demonstrate how Unity works with just a class I will throw in a Dial.cs
class in the mix also.
namespace UnityDemo
{
public class Dial
{
public string TypeOfDial { get; set; }
public Dial(string typeOfDial)
{
TypeOfDial = typeOfDial;
}
public string DialType()
{
return TypeOfDial;
}
}
}
To demonstrate how Unity deals with creation of objects whose constructors take parameters I will have a Radio.cs
too.
using System;
namespace UnityDemo
{
public class Radio : IRadio
{
public IBattery Battery { get; set; }
public ITuner Tuner { get; set; }
public string Name { get; set; }
public Radio(IBattery radioBattery, ITuner radioTuner, string radioName)
{
Battery = radioBattery;
Tuner = radioTuner;
Name = radioName;
}
public string RadioName()
{
return Name;
}
public void Start()
{
Console.WriteLine(Name + " sings: Radio Ga Ga");
}
}
}
And here is the interface IRadio.cs
which the Radio.cs
is implementing.
namespace UnityDemo
{
public interface IRadio
{
IBattery Battery { get; set; }
string Name { get; set; }
ITuner Tuner { get; set; }
string RadioName();
void Start();
}
}
And now once we have the basics, its time for Unity.
I have imaginatively named this class ContainerMagic.cs
and here it is in its full glory.
using Microsoft.Practices.Unity;
namespace UnityDemo
{
public class ContainerMagic
{
public static void RegisterElements(IUnityContainer container)
{
Dial dial = new Dial("Linear");
container.RegisterInstance(dial);
container.RegisterType<IBattery, Battery>();
container.RegisterType<ITuner, Tuner>();
var batteryType = typeof(IBattery);
var tunerType = typeof(ITuner);
container.RegisterType<IRadio, Radio>(new InjectionConstructor(batteryType, tunerType, typeof(string)));
}
}
}
There are many things going on in this. Lets go through the important lines.
* Line 07 : True to the tradition of the dependency injection, we pass an instance of Unity container to the RegisterElements
method.
* Line 09 : Here we create an object of the Dial
. A single instance of this guy is in the container. And container will return the same guy at all the places where that instance is requested. This guy is going to be shared. I will talk more about that later.
* Line 10 : We RegisterInstance this object. In other words, we tell Unity to return this object whenever the client asks for an object of type Dial
.
* Line 12 : We RegisterType the IBattery
with Battery
. We are telling Unity to create and return an object of type Battery
whenever the client asks for an object of type IBattery
.
* Line 17 : This is special. We tell Unity to create and return an object of type Radio
whenever client asks for an object of type IRadio
. The catch here is that Radio
constructor needs parameters. So we use InjectionConstructor to tell Unity what are the types of parameters the constructor of Radio
takes. See how the last parameter (which in our case is a string) is specified.
And here is client code.
using Microsoft.Practices.Unity;
using System;
namespace UnityDemo
{
public class Demo
{
private static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
ContainerMagic.RegisterElements(container);
IBattery battery = container.Resolve<IBattery>();
Console.WriteLine(battery.SerialNumber());
Dial dial = container.Resolve<Dial>();
Console.WriteLine(dial.DialType());
ITuner tuner = container.Resolve<ITuner>();
IRadio radio = container.Resolve<IRadio>(new ParameterOverride("radioBattery", battery),
new ParameterOverride("radioTuner", tuner),
new ParameterOverride("radioName", "BrokenRadio"));
radio.Start();
}
}
}
Let us see how it plays in the client code
* Line 10 : The client has to new up a UnityContainer instance.
* Line 13 : After the registration method has been called, you can demand an instance of IBattery
and Unity behind the scene will create an object of Battery
class and return it.
* Line 16 : Here Unity is resolving a class rather than an interface. It will the Dial
object which we had created. Not a very common way of using Unity.
* Line 20 : Here Unity is resolving IRadio
interface by creating and returning an object of Radio
class. Remember that Radio
constructor took parameters and we told Unity about it. Here we are passing the parameters. Notice that the name of the parameters has to match with the names we used when we registered Radio
class with Unity.
And the output is this.
You can go through the code listed above to make sense of the output. I will wait.
Named Registration
An interface usually is implemented by many classes. So when someone writes myUnityContainer.Resolve<MyDemoInterface>
, how does Unity know which class object it has to create?
Answer is Named Registration.
Let us add one interface called ISpeaker
to our sample.
namespace UnityDemo
{
public interface ISpeaker
{
void Start();
}
}
And we add two classes CheapSpeaker.cs
and PriceySpeaker.cs
implementing this interface
using System;
namespace UnityDemo
{
public class CheapSpeaker : ISpeaker
{
public void Start()
{
Console.WriteLine("Sounds cheap");
}
}
}
using System;
namespace UnityDemo
{
public class PriceySpeaker : ISpeaker
{
public void Start()
{
Console.WriteLine("Sounds Pricey");
}
}
}
The changes to the ContainerMagic.cs
will be these two lines.
container.RegisterType<ISpeaker, CheapSpeaker>("Cheap");
container.RegisterType<ISpeaker, PriceySpeaker>("Expensive");
In our client code Demo.cs
we can now ask the Unity to resolve the Interface to the particular class we want using the names we provided in the registration.
ISpeaker cheapSpeaker = container.Resolve<ISpeaker>("Cheap");
ISpeaker priceySpeaker = container.Resolve<ISpeaker>("Expensive");
cheapSpeaker.Start();
priceySpeaker.Start();
Registration by convention
This has to be the most common way of using Unity. The registration code which we saw in ContainerMagic.cs
is rather small. However it is a demo sample. In any project of significant size and complexity, the number of interfaces and implementing classes is rather large. In those cases the registration code can become huge in size. It is here that registration by convention is most useful.
All you need is to make sure that the naming convention for the interface and implementing classes is maintained. For example, if interface is IBattery
then the implementing class name should be Battery
. Then Unity will automatically map the IBattery
to Battery
.
To demonstrate it I will go back to the sample. The IBattery.cs
, Battery.cs
, ITuner.cs
and Tuner.cs
remain as such. What changes is the ContainerMagic.cs
.
It looks like this now
using Microsoft.Practices.Unity;
namespace UnityDemo
{
public class ContainerMagic
{
public static void RegisterElements(IUnityContainer container)
{
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
}
}
}
What is happening here? MSDN is the place to go for details. But in short, Unity is examining the list of implementations it has and the list of interfaces it has. Where ever there is IDemo/Demo relationship, it creates the mapping. So that when IDemo
object is needed, it creates an object of Demo
type and returns it.
The client code does not change.
using Microsoft.Practices.Unity;
using System;
namespace UnityDemo
{
public class Demo
{
private static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
ContainerMagic.RegisterElements(container);
IBattery battery = container.Resolve<IBattery>();
Console.WriteLine(battery.SerialNumber());
ITuner tuner = container.Resolve<ITuner>();
Console.WriteLine(tuner.SerialNumber());
}
}
}
See how when object of type IBattery
was asked for, Unity automatically returned an object of Battery
class. This is because at the registration time, Unity had figured out that Battery.cs
must be implementing the IBattery
interface. This turns out to be of great value. Last project I was working on had 83 registrations in the container. Needless to say we used the registration by convention.
And here is the output if you still are interested into.
Registration by convention provides a lot of flexibility. Too many to be listed here. Better look in MSDN for all the details . However there are a few which are useful. Unity allows extra information to be added once the basic mapping between the interfaces and the implementing classes is done.
Let us add yet another interface ICasing.cs
namespace UnityDemo
{
public interface ICasing
{
string TypeOfMaterial();
}
}
And let the implementing class be Casing.cs
.
namespace UnityDemo
{
public class Casing : ICasing
{
private readonly string _material;
public Casing(string material)
{
_material = material;
}
public string TypeOfMaterial()
{
return "Material used :" + _material;
}
}
}
As you might have noticed, there is a subtle issue here. The constructor of the class takes a parameter.
This information has to be added later on once the registration is done. The ContainerMagic.cs
now looks like this.
using Microsoft.Practices.Unity;
namespace UnityDemo
{
public class ContainerMagic
{
public static void RegisterElements(IUnityContainer container)
{
container.RegisterTypes(
AllClasses.FromLoadedAssemblies(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
container.RegisterType<Casing>(new InjectionConstructor("Plastic"));
}
}
}
Here the line 15 is adding information to the existing mapping between ICasing
interface and Casing
class. It is telling Unity that when it creates the object of the class Casing
for the interface ICasing
, then it should pass the parameter “Plastic” to its constructor.
The client code will be
using Microsoft.Practices.Unity;
using System;
namespace UnityDemo
{
public class Demo
{
private static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
ContainerMagic.RegisterElements(container);
IBattery battery = container.Resolve<IBattery>();
Console.WriteLine(battery.SerialNumber());
ITuner tuner = container.Resolve<ITuner>();
Console.WriteLine(tuner.SerialNumber());
ICasing casing = container.Resolve<ICasing>();
Console.WriteLine(casing.TypeOfMaterial());
}
}
}
This is a living tutorial. I will keep updating it as I get time.
Well composed and well explained
Thanks for Tutorial,
Should I have a reference to unity container to access registered objects?
Usual practice is to create an instance of Unity container in main method and then pass it to the function which does all the registrations. Then you use that container instance to get (or in Unity lingo Resolve) the objects you want.
So yes, you will need a unity container in your main code to access the registered objects.
This is an excellent tutorial to get started with Unity. Thanks! I think you forgot to include IRadio.cs, but I was able to figure out what it should have looked like. You may want to add that.
Thanks for pointing that out. Fixed.
Great Tutorial. Thanks!
Great Tutorial and very well explained. However, im having a problem when trying to add a speaker to a radio. I add another parameter to the radio constructor but when i try to run it, i got this exception:
Exception is: InvalidOperationException – The current type, Radio.Interfaces.ISpeaker, is an interface and cannot be constructed. Are you missing a type mapping?
Can you help me understand?
Like this:
public class Container
{
public static void RegisterElements(IUnityContainer container)
{
var batteryType = typeof(IBattery);
var tunerType = typeof(ITunner);
var speaker = typeof(ISpeaker);
container.RegisterType();
container.RegisterType();
container.RegisterType(“Cheap”);
container.RegisterType(“Normal”);
container.RegisterType(new InjectionConstructor(batteryType, tunerType, speaker,typeof(string)));
//container.RegisterTypes(
//AllClasses.FromLoadedAssemblies(),
//WithMappings.FromMatchingInterface,
// WithName.Default,
// WithLifetime.ContainerControlled);
}
}
public class Radio : IRadio
{
public IBattery Battery { get; set; }
public ITunner Tuner { get; set; }
public ISpeaker Speaker { get; set; }
public string Name { get; set; }
public Radio(IBattery radioBattery, ITunner radioTunner, ISpeaker speaker, string radioName)
{
this.Battery = radioBattery;
this.Tuner = radioTunner;
this.Speaker = speaker;
this.Name = radioName;
}
public string RadioName()
{
return Name;
}
public void Start()
{
Console.WriteLine(Name+” sings: song number one”);
}
}
private static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
Container.RegisterElements(container);
var battery = container.Resolve();
var tuner = container.Resolve();
var speaker = container.Resolve(“Normal”);
var radio = container.Resolve(
new ParameterOverride(“radioBattery”, battery),
new ParameterOverride(“radioTunner”, tuner),
new ParameterOverride(“Normal”, speaker),
new ParameterOverride(“radioName”, “RadioCenas”));
Console.WriteLine(battery.SerialNumeber());
Console.WriteLine(radio.Name + ” on frequency ” + tuner.Frequency());
radio.Speaker.Start();
}
I am a bit tight on time. Did not really test it out. So take this with a bag of salt.
First try to post code using code tags. I think some of your code got lost due to formatting issues.
I assume that the “Normal” type speaker is implementing “ISpeaker”. I will call that implementing class “NormalSpeaker”.
Then in container class I will register it like this:
And in the client code I will resolve it like:
And in your radio constructor you should have a parameter called "Normal". Right now it is "speaker".
So your resolving code changes to:
Thanks, it works!! the problem was the parameterName “Normal” instead of “speaker”!!
Struggled with many other tutorials out there, but now I’m fine with yours!
Thanks so much.
Thanks.
Though I will like to add that Unity is not getting actively developed. And its place in .net core looks shaky. We are planning to move over to AutoFac.Unity is back in active development. They are now releasing packages for .NET core. Sweet.
Simple and elegant tutorial.
Thanks. Did not expect this one to be so popular!!
Though keep an open mind about other containers too. Unity is not getting actively developed any more.Unity is back in active development. Woo hoo.Thanks for the Tutorial,
How does Unity eliminates dependency? Ins’t the client code just using Unity for object instantiation.
Client code works only with interfaces. In code sample you can see that client code knows about IBattery. It has no dependency on the actual class which will implement IBattery. Unity does the work of creating an object of type Battery when client demands an object implementing IBattery.
I think if your read my posts on Dependency inversion and Dependency injection it might be more clear to you.
Thanks.
This is not a good tutorial IMO in the sense that you are passing the parameters to IRadio, and not demonstrating that Unity will create those objects in the constructor for you automatically and you dont have to resolve and pass them in yourself
Thanks for comment. The tutorial is a beginner level tutorial to get people started off quickly. The ultimate reference remains the Unity Document published by Microsoft.