Unity – Part 2: Dependency Injection

Dependency Injection

Second part of my series on Unity. For an introduction, read the first post.

OK, now we know how to get Inversion of Control (IoC): instead of referencing a particular concrete implementation, we instead reference an interface or an abstract base class, which creates a level of abstraction and allows us to change things at a later time.

Now let’s see what Unity has to offer in terms of Dependency Injection (DI). DI is the process by which objects are populated (injected) with values, called dependencies, usually coming from the IoC container itself. Basically, we have three options for that:

  • Constructor injection;
  • Property injection;
  • Method injection.

What this means is, when asked for a particular instance, Unity will call a constructor, set a property’s value or invoke a method with a parameter coming from its registration. Say you have a class like this:

   1: public class MyService : IMyService
   2: {
   3:     public ILogger Logger
   4:     {
   5:         get;
   6:         private set;
   7:     }
   9:     public MyService(ILogger logger)
  10:     {
  11:         this.Logger = logger;
  12:     }
  14:     public void SetLogger(ILogger logger)
  15:     {
  16:         this.Logger = logger;
  17:     }
  18: }

Unity can inject the Logger instance by either passing a parameter on the constructor when building an instance of the MyService class, directly setting the Logger property (even with a private setter) or by invoking the SetLogger method.

Injection By Configuration

As we have seen, most things in Unity can be configured by XML configuration:

   1: <register type="MyNamespace.IMyService, MyAssembly" mapTo="MyNamespace.MyService, MyAssembly">
   2:     <constructor>
   3:         <param name="logger" dependencyType="MyNamespace.ILogger, MyAssembly" dependencyName="File"/>
   4:     </constructor>
   5:     <property name="Logger" dependencyType="MyNamespace.ILogger, MyAssembly" dependencyName="File"/>
   6:     <method name="SetLogger">
   7:         <param name="logger" dependencyType="MyNamespace.ILogger, MyAssembly" dependencyName="File"/>
   8:     </method>
   9: </register>

Did you notice the dependencyName attribute? That is the name under which the dependencyType was registered, if not set, it defaults to the empty string.

I have included both constructor, property and method injection, you usually will only need one of them.

Injection By Code

Another option is by code. When registering a type, you must add some additional code:

   1: unity.RegisterType<IMyService, MyService>(new InjectionConstructor(unity.Resolve<ILogger>("File")), new InjectionMethod("SetLogger", unity.Resolve<ILogger>("File")), new InjectionProperty("Logger", unity.Resolve<ILogger>("File")));

If you don’t want to resolve an instance yourself in InjectionMethod, InjectionConstructor or InjectionProperty, you can pass a Type and Unity will look up the actual instance for you.

Injection By Attributes

Another option is by applying attributes:

   1: public class MyService : IMyService
   2: {
   3:     [Dependency("File")]
   4:     public ILogger Logger
   5:     {
   6:         get;
   7:         private set;
   8:     }
  10:     [InjectionConstructor]
  11:     public MyService([Dependency("File")] ILogger logger)
  12:     {
  13:         this.Logger = logger;
  14:     }
  16:     [InjectionMethod]
  17:     public void SetLogger([Dependency("File")] ILogger logger)
  18:     {
  19:         this.Logger = logger;
  20:     }
  21: }

The File string is the name of the registered type.

Like previously mentioned, although I depicted all three, you will pick only one injection method. When you call Resolve or GetInstance, the instance you get will have its dependencies assigned.

Injecting Dependencies On Existing Entities

If you have some object instance that was obtained elsewhere, you can still ask Unity to inject whatever dependencies this object has. This is achieved by the BuildUp family of methods:

   1: IMyService svc = new MyService();
   3: unity.BuildUp(svc);    //Logger property is set and SetLogger method is called

Next in line: applying aspects. Stay tuned!


No Comments