Showing posts with label Unity. Show all posts
Showing posts with label Unity. Show all posts

Tuesday, 10 January 2012

10 Commandments of Inversion of Control Containers

Inversion of Control containers can be a very powerful tool for decoupling spaghetti code in large software systems. However, with any power tool, you can hurt yourself badly if you don’t use it correctly. In this post, I present “10 commandments” to help you avoid causing problems with IoC, with a particular focus on very large software systems with many developers and hundreds of interfaces. I am currently using Unity, but these tips apply to pretty much any IoC container.

1. Configure everything before your first resolve

It is possible to ask the IoC container to resolve an interface before you have finished configuring the container. So long as it knows how to make the interface you asked for and its dependencies, it will have no problem fulfilling your request. But if your application hasn’t yet finished configuring the container yet, you run the risk of getting the wrong thing. Consider the following simple example:

IUnityContainer container = new UnityContainer();
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
var f1 = container.Resolve<IFoo>();

Fairly straightforward, we ask for IFoo and get an instance of Foo. But what if we hadn’t quite finished configuring the container, and some other part in your app attempts to override the registration for IFoo:

container.RegisterType<IFoo, Foo2>(new ContainerControlledLifetimeManager());

Now, whenever we attempt to resolve IFoo, we get Foo2. But the initial component that did an early resolve is using the wrong implementation. This can make for horrible debugging sessions. Configure your container completely, before you start to resolve things from it. Which leads us to our second commandment…

2. Don’t pass the container around

What I mean here, is don’t pass around the top-level interface that allows further configuration of the container. In Unity, this is the IUnityContainer interface. It might feel very powerful to send it around, since it allows other parts of your application register new rules, but it opens the door for the kind of bugs we just discussed.

But what about just a Service Locator interface. Can I pass one of those around? Onto commandment 3…

3. Avoid passing an IServiceLocator around

Passing a service locator in as a dependency gives your class great power. It can ask for anything it wants, which is super convenient. But it also introduces some problems.

First, it means your class no longer advertises what it needs in the constructor. Without examining the code you can’t be sure what needs to be in the container for the class to work correctly. It means that unit tests, or callers of your class that aren’t using a container, will have to mock a container just to instantiate your class.

This has been called the “Hollywood principle” – Don’t call the DI Container, it’ll call you. Just put the interfaces you really need in your constructor.

4. Avoid making the container a singleton

Making your container a singleton is the quickest route to providing access to all your services everywhere in your application. It can seem like a great idea because wherever you are, you can just do this to get whatever interface you like:

var foo = MyContainer.Instance.Resolve<IFoo>();

But there are two big problems. First, this introduces hidden dependencies into your class. Instead of your constructor advertising its dependencies, we again must examine the code to know what needs to be set up in the container.

Second, it assumes that all parts of your application will work with the same container, and the same implementations of each interface. This may be true for small applications, but in large enterprise systems, there may well be the need for multiple IoC containers. In our systems, we make use of Unity child containers, allowing different sections of the application get access to their own implementations of interfaces. With a singleton container, this is impossible.

5. Avoid constructor bloat

One of the great things about IoC containers is that you don’t have to call constructors yourself – the container does the hard work for you. This means you can have a dozen constructor parameters, each representing a different dependency, and yet without ever having to write code that calls it.

public MyClass(IFoo foo, IFoo2 foo2, ILog log, IExporter exporter, IEmailer emailer, ISettings settings, IAudit audit)
{
}

That is, until you want to test it. Then you have to mock up all of those interfaces. And probably you will find that your class only needs to call one or two methods on each. This is the time to apply the Interface Segregation Principle and replace them with one or two more focussed interfaces that represent the real dependencies of your class under test.

6. Avoid property injection

Most IoC containers offer a way to let you put attributes on properties in order to tell the container that it needs to set that property after constructing the object. In Unity you use the Dependency attribute:

class Bar
{
    [Dependency]
    public IFoo Foo { get; set; }

    public Bar()
    {
    }
}

Although this seems like a great feature, it has the effect of hiding this dependency from anyone who is constructing your object without an IoC container. At the very least, your class should report a good error message if someone forgets to set up a property dependency.

7. Document your interfaces

If you are using an IoC container, chances are you are working on a large system, and other developers are resolving interfaces that you put in the container.

Often developers will add good comments to the concrete implementation of a class, but spend very little time commenting the interface (who likes to write the same comments twice?). So in the concrete class we might have a comment like this:

/// <summary>
/// Call this to process all the files in the InputFiles collection, using the rules from the Rules collection
/// </summary>
/// <param name="mode">Processing mode, 0 = replace, 1 = update, 2 = overwrite, 3 = test only</param>
public void Process(int mode)

but in the interface, we couldn’t be bothered to type that all again (and we hate cutting and pasting anyway) so we just have this:

/// <summary>
/// Process
/// </summary>
void Process(int mode);

But it is the interface that is the public API for your service. The comments on the interface will be used to display Intellisense to the user. The caller may not even have access to the code for the concrete implementation. If you are going to spend time writing good comments, write them on the interface. Here’s the difference in intellisense experience:

bad-intellisense

versus:

good-intellisense

8. Don’t depend on Dispose in a specific order

When you Dispose your IoC container, it will go through all of the IDisposable instances it knows about and call Dispose on them. But this can introduce a problem, because we cannot guarantee the order the services are disposed in. If you make a call into another service in your Dispose method, how do you know that service hasn’t already been Disposed?

Instead, design your services in such a way that they can be disposed in any order, and use events or some other form of messaging to report to your system that a shutdown is about to happen, allowing any last minute logging, saving etc to be done beforehand, while all the services are still up and running.

9. Make sure Lifetime Management is communicated

If you call Resolve<IFoo> twice on your IoC container, you might get two new instances of the Foo class, or you might get the same one twice. Without looking at how your container is configured, you have no way of knowing. But this can be a real headache if IFoo implements IDisposable. How do you know whether you ought to call Dispose on it or not?

I don’t know of any slick solution to this, but I would typically avoid instances where a Resolve gives you something you need to Dispose yourself. Instead I would return a factory object that makes it very clear you are building a new instance that you are in control of its lifetime yourself. Whatever approach you use, make sure your whole development team understands it. You don’t want someone Disposing a service too early, resulting in the next person to use it getting a nasty exception.

10. Document your public API

In a large system, a container can easily fill up with a lot of interfaces. The trouble is, not all of these are at the same level. Some are high-level interfaces, allowed to be called from anywhere, whilst other things are only in the container so they can fulfil the dependencies of those high-level interfaces. It means that you run the risk of developers guessing incorrectly about which interface they are supposed to call to achieve a particular task. They will assume that if they can get at it from the container, then they must be allowed to call it.

Now there are ways of having interfaces defined in your container that people can’t get at from the wrong place by making good use of assemblies and the internal keyword, but really, you need to make it easy for developers to know what is in the container and how they are intended to use it. This may well involve maintaining an API document, and also means writing good comments on the interface. If you don’t do this, don’t be surprised to see code that inadvertently circumvents key functionality by calling into a component at too low a level, or the wheel being reinvented, simply because a developer didn’t know the container included a service that had the desired behaviour.

Do you have any tips for getting the best out of IoC containers? Please let me know in the comments.

Tuesday, 23 November 2010

How to Register Two Interfaces as a Singleton in Unity

Every now and then I find myself wanting to configure a single implementor for multiple interfaces in Unity. Say I have the following interfaces and I only want one instance of Foo, yet I want to be able to request either IFoo or IFoo2 from the container:

public interface IFoo
{
    ...
}

interface IFoo2 : IFoo
{
    ...
}

public class Foo : IFoo2
{
    ...
}

The way I would previously go about this is:

var foo = container.Resolve<Foo>();
container.RegisterInstance<IFoo>(foo);
container.RegisterInstance<IFoo2>(foo);

This approach, works, but is less than ideal. First, it requites you to resolve something in the container, possibly before you have completely finished configuring the container (e.g. the dependencies of Foo might not be fully set up yet). Second, the container will dispose foo twice.

However, thanks to an answer from Sven Künzler to a question on Stack Overflow, there is a much better way:

container.RegisterType<Foo>(new ContainerControlledLifetimeManager());
container.RegisterType<IFoo, Foo>();
container.RegisterType<IFoo2, Foo>();
Assert.AreSame(container.Resolve<IFoo>(), container.Resolve<IFoo2>());

You simply register the concrete type as a singleton, and then point as many interfaces at that type as you like.

Monday, 7 September 2009

Custom Object Factory Unity Extension

Suppose you have an object that cannot be directly created by your IoC container. In my case, it is because that object is a .NET remoting object, so it must be created on a different computer.

One way to solve this would be to register a factory that creates your object. But in my application, there are dozens of objects that need to be created in this special way, and they all inherit from a common base interface. Ideally, I would like it to be completely transparent, so I request the type I want, and the container works out that it needs to be built in a special way.

So I set about making a Unity extension, which would allow me to intercept Resolve requests for certain interfaces, and create them using my custom factory method, or return the ones already cached.

The way to accomplish this is to create a Build Strategy, which checks to see if the requested type meets our criteria. If it does, we have a look to see if we have already cached and constructed the object. If not, we call our factory method to construct it, and cache the result. One important thing to notice is that I pass the “Context” from the extension into the build strategy. That is so that if you call Resolve from a child container, it will return the same instance as if you called it from a different child container. Obviously, your requirements may differ.

The if statement in PreBuildUp contains my rule for deciding if this is a Resolve request I want to intercept. Again, this could be customised for any arbitrary logic.

public class FactoryMethodUnityExtension<T> : UnityContainerExtension
{
    private Func<Type,T> factory;

    public FactoryMethodUnityExtension(Func<Type,T> factory)
    {
        this.factory = factory;
    }

    protected override void Initialize()
    {
        var strategy = new CustomFactoryBuildStrategy<T>(factory, Context);

        Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);            
    }
}

public class CustomFactoryBuildStrategy<T> : BuilderStrategy
{
    private Func<Type,T> factory;
    private ExtensionContext baseContext;

    public CustomFactoryBuildStrategy(Func<Type,T> factory, ExtensionContext baseContext)
    {
        this.factory = factory;
        this.baseContext = baseContext;
    }

    public override void PreBuildUp(IBuilderContext context)
    {
        var key = (NamedTypeBuildKey)context.OriginalBuildKey;

        if (key.Type.IsInterface && typeof(T).IsAssignableFrom(key.Type))
        {
            object existing = baseContext.Locator.Get(key.Type);
            if (existing == null)
            {
                // create it
                context.Existing = factory(key.Type);
                
                // cache it
                baseContext.Locator.Add(key.Type, context.Existing);
            }
            else
            {
                context.Existing = existing;
            }
        }
    }
}

Using the extension is very simple. Simply give it the delegate to use to create the objects, and register it as an extension:

WhateverFactory factory = new WhateverFactory();
container = new UnityContainer();
container.AddExtension(new FactoryMethodUnityExtension<IWhatever>(factory.Create));

Here’s a couple of blog posts I found helpful while trying to learn how to create a Unity extension:

Thursday, 20 August 2009

Lazy Loading of Dependencies in Unity

I have been learning the Unity IoC container recently as we will be making use of it in a project I am working on. Like all IoC containers, it makes it nice and easy to automatically construct an object, fulfilling all its dependencies.

One issue that comes up frequently when using IoC containers, is how to implement lazy loading. For example, suppose my class has a dependency on IEmailSender, but only uses it in certain circumstances. I might not wish for the concrete implementation to be created until I actually know I need it.

public class MyClass(IEmailSender emailSender)

One quick way round this is to take a dependency on the container instead. With Unity, the container comes already registered, so you can simply change the constructor prototype. Now you can call container.Resolve<IEmailSender> at the point you are ready to use it.

public class MyClass(IUnityContainer container)

The disadvantage of this solution is that we have now obscured the real dependencies of MyClass. It could ask for anything it likes from the container, and we have to examine the code to find out what it actually uses. Fortunately, there is a way we can solve this using Unity’s ability to allow you to register open generic types.

Suppose we create a generic class called Lazy, that implements ILazy as follows:

public interface ILazy<T>
{
    T Resolve();
    T Resolve(string namedInstance);
}

public class Lazy<T> : ILazy<T>
{
    IUnityContainer container;

    public Lazy(IUnityContainer container)
    {
        this.container = container;
    }

    public T Resolve()
    {
        return container.Resolve<T>();
    }

    public T Resolve(string namedInstance)
    {
        return container.Resolve<T>(namedInstance);
    }
}

Now we need to tell our container to use Lazy when someone asks for ILazy:

container.RegisterType(typeof(ILazy<>),typeof(Lazy<>));

And now that allows us to change our original class to have the following prototype:

public class MyClass(ILazy<IEmailService> emailServiceFactory)

Now we have advertised that our class depends on an IEmailService, but have not created it immediately on construction of MyClass, nor have we allowed MyClass to get at the IUnityContainer itself.