March 1, 2012

Simple Generic ServiceLocator example

Find the root of all evil behind this pattern by Martin Fowler
What's the difference between the Dependency Injection and Service Locator patterns?

Here is a simple GenericServiceLocator class:
public class GenericServiceLocator
{
    #region Fast Thread Safe Singleton Implementation
        
    static GenericServiceLocator()
    {}

    private GenericServiceLocator()
    {}

    private static readonly GenericServiceLocator instance = 
        new GenericServiceLocator();

    public static GenericServiceLocator Instance
    {
        get
        {
            return instance;
        }
    }

    #endregion Fast Thread Safe Singleton Implementation

    Dictionary<object, object> interfaceToServiceMap = 
        new Dictionary<object, object>();

    public void AddService<IInterface>(IInterface svcImpl)            
    {
        Trace.Assert(typeof(IInterface).IsInterface);
        Trace.Assert(svcImpl != null);
        Trace.Assert(svcImpl is IInterface);
        Trace.Assert(!this.interfaceToServiceMap.
                               ContainsKey(typeof(IInterface)));
        this.interfaceToServiceMap[typeof(IInterface)] = svcImpl;
    }


    public IInterface GetService<IInterface>() 
    {
        Trace.Assert(typeof(IInterface).IsInterface);
        

        object obj = this.interfaceToServiceMap[typeof(IInterface)];
        return (IInterface)obj;
    }


    public bool HasService<IInterface>()
    {
        Trace.Assert(typeof(IInterface).IsInterface);

        return this.interfaceToServiceMap.
                                   ContainsKey(typeof(IInterface));
    }
}
Here is a simple tester for it:
class TestServiceLocator
{
    public interface IMyPieInterface
    {
        double GetPie();
    }

    public class PieMaker : IMyPieInterface
    {
        #region IMyPieInterface Members

        public double GetPie()
        {
            return Math.PI;
        }

        #endregion
    }

    public void Test()
    {
        GenericServiceLocator.Instance.
                          AddService<IMyPieInterface>(new PieMaker());
        Trace.Assert(GenericServiceLocator.Instance.
                          HasService<IMyPieInterface>());

        IMyPieInterface myPieMaker = GenericServiceLocator.Instance.
                          GetService<IMyPieInterface>();
        double pie = myPieMaker.GetPie();
        Trace.Assert(Math.Abs(Math.PI - pie) < 0.001);
    }
}

No comments: