A Singleton Service Locator Pattern

This is the third post of a series on the Service Locator pattern. In the first post I described how to create a basic service locator for your C# application, while in the second post I introduced lazy initialization of the services.

We now add another piece to our puzzle, transforming the Service Locator class into a singleton.

The Singleton Pattern

The singleton is arguably the most known and controversial design pattern. Some say singletons are good, some says singletons are evil. Eric Gamma himself (one of the Gang Of Four) in a recent interview stated that (emphasis added):

When discussing which patterns to drop, we found that we still love them all. (Not really—I’m in favor of dropping Singleton. Its use is almost always a design smell.)

I don’t have a strong opinion either way; I tend to use it sparingly and in the following code I will show how to apply this pattern to the service locator. There are already countless blogs discussing the pros and the cons of the singleton pattern, therefore I won’t discuss about it any further.

The Singleton Service Locator

The following was our initial implementation (other details of the classes have been removed for clarity). The constructor was internal, allowing all potential clients from within the assembly to invoke it. Clients could either pass around a reference to the created service locator, or instantiate new instances each time:

internal class ServiceLocator : IServiceLocator
{
    // a map between contracts -> concrete implementation classes
    private IDictionary<Type, Type> servicesType;

    // a map containing references to concrete implementation already instantiated
    // (the service locator uses lazy instantiation).
    private IDictionary<Type, object> instantiatedServices;

    internal ServiceLocator()
    {
        this.servicesType = new Dictionary<Type, Type>();
        this.instantiatedServices = new Dictionary<Type, object>();

        this.BuildServiceTypesMap();
    }

    // rest of the methods
 }

To implement the singleton pattern, we make the constructor private and provide clients with a static method through which we can retrieve an instance of the service.

Note how the creation of the single instance of the ServiceLocator class is itself lazy and thread safe. There are a few variations on the theme when it comes to singleton thread safe initialization (see for example this post by Jon Skeet).

internal class ServiceLocator : IServiceLocator
{
        // a map between contracts -> concrete implementation classes
        private IDictionary<Type, Type> servicesType;
        private static readonly object TheLock = new Object();

        private static IServiceLocator instance;

        // a map containing references to concrete implementation already instantiated
        // (the service locator uses lazy instantiation).
        private readonly IDictionary<Type, object> instantiatedServices;

        private ServiceLocator()
        {
            this.servicesType = new Dictionary<Type, Type>();
            this.instantiatedServices = new Dictionary<Type, object>();

            this.BuildServiceTypesMap();
        }

        public static IServiceLocator Instance
        {
            get
            {
                lock (TheLock) // thread safety
                {
                    if (instance == null)
                    {
                        instance = new ServiceLocator();
                    }
                }

                return instance;
            }
        }

        // rest of the methods
 }

Clients will now simply invoke the GetService() method through the singleton instance, without having to create a new object each time:

IServiceA service = ServiceLocator.Instance.GetService<IUniverseFileServiceAdapter>();


kick it on DotNetKicks.com


Shout it

Bookmark and Share

Technorati Tags: , , ,
This entry was posted in .NET, C#, Design and Patterns and tagged , , . Bookmark the permalink.
  • Pingback: DotNetShoutout

  • http://www.tariqulazam.info Md Tariq Ul Azam

    Thats great and handy indeed. I was looking for something simple and found this one as the simplest.

    Thanks for this mate. Keep up the good work.

  • http://www.tariqulazam.info Md Tariq Ul Azam

    Thats great and handy indeed. I was looking for something simple and found this one as the simplest.

    Thanks for this mate. Keep up the good work.

  • stefanoricciardi

    Tariq,

    glad you’ve found this helpful. Indeed, you can find out there full fledged IoC containers with all the bells and whistles. But sometime something this simple is all you need.

    Stefano

  • stefanoricciardi

    Tariq,

    glad you’ve found this helpful. Indeed, you can find out there full fledged IoC containers with all the bells and whistles. But sometime something this simple is all you need.

    Stefano

  • http://profile.yahoo.com/IX4QW3CSXXG7QAJ7MHJMV2DCLA Madaximus

     
    I enjoyed your article about Service Locator Pattern.  Do you have a project with code examples?

  • stefanoricciardi

     @yahoo-IX4QW3CSXXG7QAJ7MHJMV2DCLA:disqus: I haven’t got access to the code base from which this snippets had been extracted anymore.

    Consider than as soon as your requirements for this locator complicates a bit, you should consider one of the excellent full fledged IoC containers out there (e.g. Ninject, Castle-Windsor, etc…).

  • Jorge Rodrigues

    Hi,

    Can I use IServiceA service = ServiceLocator.Instance.GetService();

    ?