Skip to content

Service Locator Pattern in C# with Lazy Initialization

2009 October 13
by stefanoricciardi

In my previous post Service Locator Pattern in C#: A Simple Example I introduced a fairly basic implementation of this pattern. In this post I will address one of the limitations of that implementation, introducing a form of lazy initialization.

Defining Lazy Initialization

Lazy initialization improves the performance of object creation, deferring long running initializations until they are really needed.

Suppose for example that some of the fields of an object need to be read from the database. If a client never access those fields, accessing the database to retrieve those fields has been useless and it has just made object initialization slower (often by a considerable factor).

Martin Fowler credits Kent Beck with the introduction of the lazy initialization pattern, and in PoEAA book he describes it in the following way:

The basic idea is that every access to the field checks to see if it’s null. If so, it calculates the value of the field before returning the field. To make this work you have to ensure that the field is self-encapsulated, meaning that all access to the field, even from within the class, is done through a getting method.

Fairly simple.

The Improved Service Locator

The following is the improved version of the service locator which uses lazy initialization of the services.

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();
    }

    public T GetService<T>()
    {
        if (this.instantiatedServices.ContainsKey(typeof(T)))
        {
            return (T)this.instantiatedServices[typeof(T)];
        }
        else
        {
            // lazy initialization
            try
            {
                // use reflection to invoke the service
                ConstructorInfo constructor = servicesType[typeof(T)].GetConstructor(new Type[0]);
                Debug.Assert(constructor != null, "Cannot find a suitable constructor for " + typeof(T));

                T service = (T)constructor.Invoke(null);

                // add the service to the ones that we have already instantiated
                instantiatedServices.Add(typeof(T), service);

                return service;
            }
            catch (KeyNotFoundException)
            {
                throw new ApplicationException"The requested service is not registered");
            }
        }
    }

    private void BuildServiceTypesMap()
    {
        servicesType.Add(typeof(IServiceA),
            typeof(ServiceA));

        servicesType.Add(typeof(IServiceB),
            typeof(ServiceB));

        servicesType.Add(typeof(IServiceC),
            typeof(ServiceC));
     }
}

We are now maintaining two separate maps:

  • servicesType maps an interface describing a service to a type T that implements that interface.
  • instantiatedServices maps an interface to an instantiated object of class T.

Both maps are initialized in the constructor. However only the first map is filled. Every time GetService is invoked, we check whether a concrete implementation of that service has already been created. If not, we create that service implementation retrieving its constructor via reflection, and we put a reference to that implementation in the instantiatedServices map.

For this to work, the service implementation needs to expose a default (parameterless) constructor.

If services creation time is significant, lazy initialization can save you quite some time during application start up, with very little cost in terms of increased complexity.

Next article in the series: A Singleton Service Locator

Bookmark and Share

Technorati Tags: , , ,

  • Steven

    Hello, I’ve used something very similar after discovering the Service Locator pattern.

    Why have you chosen to register services within the class instead of providing it as a public method?

    I like the idea of the lazy loading but was wondering, is there a way for the services to be disposed (or unreferenced) when they’re no longer referenced by anything other than the ServiceLocator?

    Thanks :) .

  • Steven

    Hello, I’ve used something very similar after discovering the Service Locator pattern.

    Why have you chosen to register services within the class instead of providing it as a public method?

    I like the idea of the lazy loading but was wondering, is there a way for the services to be disposed (or unreferenced) when they’re no longer referenced by anything other than the ServiceLocator?

    Thanks :) .

  • Stefano Ricciardi

    Steven,

    you are quite right: providing a method to register services is really the way to go for a complete service locator implementation.

    In my specific case I had more limited requirements, having full control of the services that had to be instantiated at run time. So I preferred to “keep it simple”.

    About disposing of the services when not needed… well I admit that I hadn’t put much thought into that. I doubt that the service locator itself could/should implement some sort of reference counting.

    It would be interesting to investigate whether mature service locator implementations (Castle Windsor, Spring.NET, StructureMap, etc…) have tackled this kind of problem and how they solved it.

  • Stefano Ricciardi

    Steven,

    you are quite right: providing a method to register services is really the way to go for a complete service locator implementation.

    In my specific case I had more limited requirements, having full control of the services that had to be instantiated at run time. So I preferred to “keep it simple”.

    About disposing of the services when not needed… well I admit that I hadn’t put much thought into that. I doubt that the service locator itself could/should implement some sort of reference counting.

    It would be interesting to investigate whether mature service locator implementations (Castle Windsor, Spring.NET, StructureMap, etc…) have tackled this kind of problem and how they solved it.

  • Cameron

    “It would be interesting to investigate whether mature service locator implementations (Castle Windsor, Spring.NET, StructureMap, etc…) have tackled this kind of problem and how they solved it.”

    I think they use weak references (http://msdn.microsoft.com/en-us/library/system.weakreference.aspx)
    But I guess that’s the benefit of having a custom service locator class – if you don’t need the logic for instance lifetime management then you can leave it out.

  • Cameron

    “It would be interesting to investigate whether mature service locator implementations (Castle Windsor, Spring.NET, StructureMap, etc…) have tackled this kind of problem and how they solved it.”

    I think they use weak references (http://msdn.microsoft.com/en-us/library/system.weakreference.aspx)
    But I guess that’s the benefit of having a custom service locator class – if you don’t need the logic for instance lifetime management then you can leave it out.

  • http://www.sourcingvision.com Alex Goldman

    Hi,

    There is small problem using Dictionary, Some times custom class that you create new instance they inherit several interfaces.

    I using IList : TheList.OfType(the Interface)

  • http://www.sourcingvision.com Alex Goldman

    Hi,

    There is small problem using Dictionary, Some times custom class that you create new instance they inherit several interfaces.

    I using IList : TheList.OfType(the Interface)

  • Phill

    There is no need to go to that much trouble… by adding a new() constraint to your generic parameter then you can insure that they have a default constructor and call that directly:

    public T GetService() : where T : class, new()
    19 {
    20 if (this.instantiatedServices.ContainsKey(typeof(T)))
    21 {
    22 return (T)this.instantiatedServices[typeof(T)];
    23 }
    24 else
    25 {
    26
    33 T service = new T();
    34
    35 // add the service to the ones that we have already instantiated
    36 instantiatedServices.Add(typeof(T), service);
    37
    38 return service;
    39 }
    40 catch (KeyNotFoundException)
    41 {
    42 throw new ApplicationException”The requested service is not registered”);
    43 }
    44 }
    45 }

    Note, there may be some errors in that but the concept is sound.

  • Anonymous

    Phill,

    thank you for your comment. Your solution seems to be cleaner and more
    efficient.

  • http://pulse.yahoo.com/_OVH5HCETJPZ2UZ72X7QAELJLSU LegoMyEgo

    I tried using this method of constraining the Generic type to class, new() and it doesnt work because when using the GetService the T your usually passing in an Interface.  So.. the interface is an abstract type with no constructor.. so this does not work.  The example he has given the the blog works fine.. but your implementation here fails.

  • Foo

    why not use Lazy ?

  • Anonymous

    Lazy has been introduced with .NET 4, which had not been released yet at the time of writing this post.

  • http://istacee.wordpress.com Istace Emmanuel

    I’m using Activator.CreateInstance(T); on the GetService(T) and i store pair of Interface/ImplementationType into the dictionnary. Sound it as a good solution ?

  • Anonymous

    Yes, that should work as well. Remember the goal of this post is to show a simple example, not to re-write a full fledged IOC container.

0 visitors online now
0 guests, 0 bots, 0 members
Max visitors today: 0 at 12:02 am CET
This month: 0 at 02-01-2012 12:00 am CET
This year: 48 at 01-13-2012 02:02 pm CET
All time: 82 at 01-24-2011 04:41 pm CET