Unity container and the Decorator Pattern

Posted by dariosantarelli on September 12, 2012

In these days I’m using Unity as IoC and DI container in a project. One of the “must-have” features of a modern container is the ability to be configured at runtime, preferably with a  fluent mapping registration interface. Moreover, one of the expected features is the support for decorator or chain object pattern configurations with intuitive code. A simple scenario could be something like this:

public interface IService {}

public class Service : IService {}

public class ServiceDecorator : IService
  protected IService DecoratedService { get; private set; }

  public ServiceDecorator(IService service)
    DecoratedService = service;

The intent is straightforward and quite common: registering the relationship between the Service and the ServiceDecorator class, so when someone asks for an IService, he gets a Service instance wrapped in a ServiceDecorator instance. Let’s have a look at the most used solutions.


Solution 1: Using an InjectionConstructor

Well, configuring the Unity container to support a decorator in the old-fashioned way requires some not so much readable code. In fact, making this work seems a kind of magic.

public void UnityContainer_Should_Resolve_The_ServiceDecorator_With_InjectionConstructor()
  var container = newUnityContainer();
  container.RegisterType<IService, Service>(“Service”);
                new InjectionConstructor(new ResolvedParameter(typeof(IService), “Service”)));
  var service = container.Resolve<IService>();
  Assert.IsInstanceOfType(service, typeof(ServiceDecorator));


I think the code above is not optimal, because it uses magic strings.  It also has a dangerous disadvantage: changes to the ServiceDecorator constructors will generate runtime instead of compile time errors.


Solution 2: Using an InjectionFactory

This is a substantial improvement of the previous solution. It allows to specify a factory function which can use the injected container to explicitly resolve eventual dependencies to decorated/decorator constructors.

public void UnityContainer_Should_Resolve_The_ServiceDecorator_With_InjectionFactory()
 var container = new UnityContainer();
 Func<IUnityContainer, object> factoryFunc = c => new ServiceDecorator(new Service(
       // Here you can use the container to resolve further dependencies…

 container.RegisterType<IService>(new InjectionFactory(factoryFunc));

 var service = container.Resolve<IService>();
 Assert.IsInstanceOfType(service, typeof(ServiceDecorator));

The downside is that code still needs updating every time a new constructor parameter is added to Service or ServiceDecorator class. But now we have three noticeable advantages:

  • code is much easier to understand
  • only a single registration into the container is required
  • changes to the constructors will generate compile time instead of runtime errors.


Solution 3: Using a custom Unity Container Extension

You can use a container extension like this DecoratorContainerExtension in order to use the same convention available for example in the Castle Windsor container:

public void UnityContainer_Should_Resolve_The_ServiceDecorator_With_DecoratorContainerExtension()
  var container = new UnityContainer();
  container.RegisterType<IService, ServiceDecorator>();
  container.RegisterType<IService, Service>(); 
  var service = container.Resolve<IService>();
  Assert.IsInstanceOfType(service, typeof(ServiceDecorator));

This is absolutely my favourite solution.  It’s less code, and most importantly it describes the intent in a better way, because it’s focused on the developer’s object model and not the on the Unity’s one.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: