It's time to take a step back from the whole debate about whether or not Service Locator is, or isn't, an anti-pattern. It remains my strong belief that it's an anti-pattern, while others disagree. Although everyone is welcome to think differently than me, I've noticed that some of the arguments being put forth in defense of Service Locator seem very convincing. However, I believe that in those cases we no longer talk about Service Locator, but something that looks an awful lot like it.

Some APIs are easy to confuse with a ‘real' Service Locator. It probably doesn't help that last year I published an article on how to tell the difference between a Service Locator and an Abstract Factory. In this article I may have focused too much on the mechanics of Service Locator, but as Derick Bailey was so kind to point out, this hides the role the API might play.

To repeat that earlier post, a Service Locator looks like this:

public interface IServiceLocator
{
    T Create<T>(object context);
}

All Service Locators I've seen so far look like that, or some variation thereof, but that doesn't mean that the relationship is transitive. Just because an API looks like that it doesn't automatically means that it's a Service Locator.

If it was, all DI containers would be Service Locators. As an example, here's Castle Windsor's Resolve method:

public T Resolve<T>()

Even AutoFixture has an API like that:

MyClass sut = fixture.CreateAnonymous<MyClass>();

It has never been my intention to denounce every single DI container available, as well as my own open source framework. Service Locator is ultimately not identified by the mechanics of its API, but by the role it plays.

A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.

It becomes a Service Locator if used incorrectly: when application code (as opposed to infrastructure code) actively queries a service in order to be provided with required dependencies, then it has become a Service Locator.

Service Locators are spread thinly and pervasively throughout a code base - that is just as much a defining characteristic.


Comments

Jan
Sorry to come back to this pattern/anti-pattern discussion but when I get this right, a ServiceLocator per se is not an anti-pattern if used canny and wise.
The anti-pattern comes from a DI container used as a ServiceLocator?
2011-08-26 08:53 UTC
Service Locator is, in my opinion, always an anti-pattern. However, a class with a Service Locator-like signature does not in itself constitute a Service Locator - it has to be used like a Service Locator to be one.

A DI Container is not, in itself, a Service Locator, but it can be used like one. If you do that, it's an anti-pattern, but that doesn't mean that any use of a container constitutes an anti-pattern. When a container is used according to the Register Resolve Release pattern from within a Composition Root it's all good.
2011-08-26 09:22 UTC
wcoenen
I am confused by your use of the word "transitive" here (and also in your book on page 3). Don't you mean "symmetric" instead of "transitive"?
2011-08-26 15:34 UTC
Yes, well, nobody's perfect :/ Thanks for pointing that out. My mistake. 'Symmetric' is the correct term - I'll see if I can manage to include that correction in the book. It's close, but I think it'll be possible to correct it.
2011-08-28 19:41 UTC
Hi, Mark,

I pop by your blog intermittently: it's good stuff.

For some reason, I always had a particular idea of the type of person you are; but for some other reason, I thought that this stemmed from something other than your (excellent) writings.

I've just realised what it is.

That photo of you, up there on the top right, your, "Contact," photo.

It looks like you have an ear-ring dangling from your left ear.
2011-09-03 16:38 UTC
Tuan Nguyen
Hi Mark,

I have one concern about Composition Root. For WPF applications, you said that the Composition Root is at OnStartUp. So, if I want to compose the main window and all other windows (with their view models) in the app at once and one place only (I mean at OnStartUp). How could I do? Thanks in advance!
2011-12-04 18:28 UTC
Composing an object graph in WPF is no different than in any other application. In WPF, using the MVVM pattern, you shouldn't compose Windows but rather ViewModels. In the case where the ViewModels rely on run-time values, you can use an Abstract Factory.
2011-12-05 10:46 UTC
Tuan Nguyen
Thank you for your answer. I still have another question about your book. I am reading on Chapter 14 - Part 4. You said that Unity doesn't have built-in support to auto-registration. So, you suggested using reflection and Register method. I tried to apply your solution to my example with Unity 2.3 but it didn't work. Can you investigate where I am wrong? Following is the source code:

namespace SimpleCSharpApp
{
class Program
{
static void Main(string[] args)
{
// resolve object using Unity
IUnityContainer container = new UnityContainer();
foreach (var t in typeof(Program).Assembly.GetExportedTypes())
{
if (typeof(IMessageWriter).IsAssignableFrom(t))
{
container.RegisterType(typeof(IMessageWriter), t, t.FullName);
}
}
container.Resolve<Salutation>().Exclaim();
Console.ReadLine();
}
}

public class Salutation
{
private readonly IMessageWriter writer;
public Salutation(IMessageWriter writer)
{
this.writer = writer;
}

public void Exclaim()
{
writer.Write("Hello DI!");
}
}

public interface IMessageWriter
{
void Write(string message);
}

public class ConsoleMessageWriter : IMessageWriter
{
public void Write(string message)
{
Console.WriteLine(message);
}
}

}
2011-12-07 18:06 UTC
Does the code download for the book work for you?
2011-12-07 18:21 UTC
_, Doing some searching as well as noticed your website appears a bit all messed up during my K-meleon web browser. However luckily barely anybody uses it any longer however you might want to consider it.
2012-04-03 11:49 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or Google Plus, or somewhere else with a permalink. Ping me with the link, and I may add it as a comment.

Published

Thursday, 25 August 2011 18:55:12 UTC

Tags