Skip to content

IoC: Static Service Locator

Antony Male edited this page Apr 8, 2015 · 5 revisions

Caliburn.Micro came with a static service locator called IoC. This let you access the IoC container from anywhere in your code, like this:

var vm = IoC.Get<MyDialogViewModel>();
this.windowManager.ShowDialog(vm);

Stylet doesn't include an equivalent, and with good reason: I don't want to encourage people to write such horrible code. The Service Locator pattern is frequently termed an anti-pattern. Every class now has a dependency on IoC (instead of the actual classes it depends on), and you can't tell just by looking at the class's constructor what its dependencies are: you have to scour through the code for calls to IoC.Get.

IoC was also used internally within Caliburn.Micro to get around some poor design choices. These have been re-architected in Stylet, and so IoC is no longer required internally.

If you really really need IoC back (and it's a deal-breaker), then you can write your own very easily. First create this static IoC class:

public static class IoC
{
    public static Func<Type, string, object> GetInstance = (service, key) => { throw new InvalidOperationException("IoC is not initialized"); };

    public static Func<Type, IEnumerable<object>> GetAllInstances = service => { throw new InvalidOperationException("IoC is not initialized"); };

    public static Action<object> BuildUp = instance => { throw new InvalidOperationException("IoC is not initialized"); };

    public static T Get<T>(string key = null)
    {
        return (T)GetInstance(typeof(T), key);
    }

    public static IEnumerable<T> GetAll<T>()
    {
        return GetAllInstances(typeof(T)).Cast<T>();
    }
}

Then wire it into your bootstrapper like this:

protected override void Configure()
{
   IoC.GetInstance = this.Container.Get;
   IoC.GetAllInstances = this.Container.GetAll;
   IoC.BuildUp = this.Container.BuildUp;
}
Clone this wiki locally