Why does Unity use a Service Locator?

Travis J picture Travis J · Feb 3, 2012 · Viewed 13.7k times · Source

I have seen this line of code in several tutorials for using Unity in asp.net mvc3. I was under the impression that Service Locator is an anti-pattern and not best practice. Is this Service Locator something other than the anti-pattern defined, or is this line of code / this implementation considered bad practice.

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));

Answer

G. Lombard picture G. Lombard · Aug 23, 2013

Old question, but for the benefit of others:

While I absolutely agree with the mantra "Service Location is an anti-pattern", there are definitely exceptions to that rule.

When you use Dependency Injection (like Unity) then, yes, certainly don't use ServiceLocator and only use constructor injection for all your service classes. (Also don't use "new" for anything other than value objects like DTOs.)

However, there are cases where you simply can't use constructor injection and then the only way to get access to a service is to use a workaround to access your Unity container directly, and in such cases, ServiceLocator is a good standard way to accomplish that. This is the case when the class isn't instantiated by you (or more specifically, it isn't instantiated by Unity) but by the .NET framework for example.

A few simple examples of where ServiceLocator might be useful, is to get access to services registered in your Unity container from:

  1. an implementation of a WCF IEndpointBehavior or IClientMessageInspector
  2. an implementation of a WPF IValueConverter
  3. or you may not necessarily even want to get access to "services" from the class, but you simply want to write code that is unit-testable, but for some reason the class can't be instatiated at all (or not easily) because it would normally be constructed by the .NET Framework, so you extract your custom code into a class that is testable, and resolve it in the non-testable class using the ServiceLocator.

Note that this line is not ideal:

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));

The ServiceLocator.Current property is going to execute the delegate provided every time you access Current, i.e. a new UnityServiceLocator is going to get created every time. Instead, you probably want to do this:

IServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);