This came up on the Alt.Net Yahoo Group/mailing list today.  There are tons of tools out there for inversion of control.  They have been compared here and other places online.  Nobody wants their app tied to the Betamax of IoC tools, so people are anxious to pick the best one.

All containers keep a hash table of your interfaces mapped to your concrete classes.  Most will let you request a specific instance with a string token.  Most will let you control instance creation (singleton, etc.).  The popular IoC containers have fluent configuration and use conventions to figure out that IEmailService maps to EmailService.

So which one should you pick?  Go with the one you already know best and/or the one that is easiest for your dev team to configure.  That's because with the Common Service Locator wrapping your IoC get instance calls, the provider becomes a moot point.

This is an old OO principal - encapsulate the stuff that can change.  Jeremy Miller pointed out the need for a common IoC wrapper to do just this.  Today's hot new open source IoC container could be tomorrow's dormant project.  If you wrap the calls, you can rip out your IoC provider and most of your code stays the same since it's calling the wrapper.

Here's how I'm doing this using Castle Windsor in a Sharp Architecture project.  First, I create a class to wire up my IoC configurations for my app.

public static class RegisterIoCContainer
{
    public static void AddComponentsTo(IWindsorContainer container)
    {
        AddApplicationConcernsTo(container);
        AddCoreConcernsTo(container);
    }

    private static void AddApplicationConcernsTo(IWindsorContainer container)
    {
        container.Register(Component
            .For<IMappingEngine>
            .Instance(Mapper.Engine)
            .LifeStyle.Singleton);

        container.Register(AllTypes.Pick()
            .FromAssemblyNamed("MyApp.ApplicationServices")
            .WithService.FirstInterface()
            .Configure(c => c.LifeStyle.Transient));
    }

    private static void AddCoreConcernsTo(IWindsorContainer container)
    {
        container.Register(AllTypes.Pick()
            .FromAssemblyNamed("MyApp.Infrastructure")
            .WithService.FirstNonGenericCoreInterface("MyApp.Core")
            .Configure(c => c.LifeStyle.Transient));
    }
}

Note the use of convention-based mappings between assemblies and the different instance lifestyles.  Mapper.Engine has a Singleton lifestyle.  Not that there's anything wrong with that. :>

Next, I create a class to tell Common Service Locator to use Castle Windsor as the provider and to load up those IoC configurations:

public static class RegisterServiceLocator
{
    public static void Register()
    {
        var container = new WindsorContainer();

        ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(container));

        RegisterIoCContainer.AddComponentsTo(container);
    }
}

Then I call RegisterServiceLocator.Register() on Application_Start() in the Global.asax.  From then on, I can call the Common Service Locator to get my instance from my interface:

var instance = ServiceLocator.Current.GetInstance<IEmailService>();

I don't often need to use this syntax, since I'm usually pushing external dependencies into a constructor and letting auto-wiring resolve the dependency chain for me.  But I do use this syntax for testing that Common Service Locator is finding the instance I want.