Welcome to the navigation

Aliqua, anim deserunt voluptate cillum enim elit, aliquip in non qui eiusmod et ex quis minim ea id consequat, pariatur, do officia nostrud nisi irure. Sed sunt adipisicing quis est ea sit dolore dolor ut et ex id consectetur enim incididunt deserunt duis elit, consequat, laboris excepteur ut irure ut

Yeah, this will be replaced... But please enjoy the search!

ServiceLocator Singleton Pattern With Annotation Mapping

The Goal

I needed something simple but highly customizable and testable with the ability to initialize and bind class instances using annotations. I got inpsired by the way EPiServer constructed their ServiceLocator and how easy it is to register the types with class annotations. I wrapped it and used Microsoft Unity for the IoC.

Concepts

IoC

The basic principle of IoC is that high level or low level modules should not depend upon each other, instead they should depend upon abstractions, it is also sometimes called the Dependency Inversion Principle (DIP) or even better referred to as the Hollywood Principle – “Don’t call us, we will call you”.

Microsoft Unity

Unity is a general-purpose container for use in any type of Microsoft.NET Framework-based application. It provides all of the features commonly found in dependency injection mechanisms, including methods to register type mappings and object instances, resolve objects, manage object lifetimes, and inject dependent objects into the parameters of constructors and methods, and as the value of properties of objects it resolves. 

https://msdn.microsoft.com/en-us/library/dn170416.aspx

Service Locator

You can think of a service locator as a registry that you can look up an instance of an object or service that another class in your application created and registered with the service locator. When using a service locator, every class will have a dependency on your service locator (unlike when you use dependency injection).

Implementation

In the example below I've created and implemented two interfaces, one with a message and one with a number. The classes is registered in the IoC Container using the Inject annotation.

public interface IServiceA
{
    string Message { get; set; }
}
 
[Inject(type: typeof(IServiceA), singleton: true)]
public class ServiceA : IServiceA {
    public string Message { get; set; }
}
public interface IServiceB
{
    int Number { get; set; }
}
 
[Inject(type: typeof(IServiceB), singleton: true)]
public class ServiceB : IServiceB
{
    public int Number { get; set; }
}

Constructor injection of interface instances in a new class

public class ClassA
{
    private readonly IServiceA _serviceA;
    private readonly IServiceB _serviceB;
 
    public ClassA(IServiceA a, IServiceB b)
    {
        _serviceA = a;
        _serviceB = b;
    }
 
    public void Check()
    {
        Console.WriteLine($"Message: {_serviceA.Message}");
        Console.WriteLine($"Number: {_serviceB.Number}");
    }
}

Some of my goals was to keep it simple to implement, simple to use and to get a somewhat versitale lifetime management. There are several lifetime managers, read more on them in the article Understanding Lifetime Managers on MSDN

I descided to support the default TransientLifetimeManager (creates and returns a new instance of the requested type for each call to the Resolve or ResolveAll method) and the singleton ContainerControlledLifetimeManager (registers an existing object as a singleton instance) by implementing a singleton attribute in the constructor of the attribute class.

public sealed class InjectAttribute : Attribute
{
    public Type RegisteredType;
    public LifetimeManager LifetimeManager;
 
    public InjectAttribute() { }
 
    public InjectAttribute(Type type)
    {
        RegisteredType = type;
    }
    public InjectAttribute(Type type, bool singleton)
    {
        RegisteredType = type;
        LifetimeManager = singleton ? new ContainerControlledLifetimeManager() : null;
    }
}

As already shown above this is used as a class annotation

[Inject(type: typeof(IServiceA))]
public class TransistentClassA : IServiceA // ...
[Inject(type: typeof(IServiceA), singleton: true)]
public class SingletonClassA : IServiceA // ...

The Service Locator Singleton

As stated earlier the service locator is a registry where we can go when we need an instance of an object or service that another class in your application created and registered. In this implementation there's a boostraper called from the singleton constructor registering all classes that use the InjectAttribute annotation.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
 
public class ServiceLocator
{
    #region Singleton
 
    private static readonly ServiceLocator instance = new ServiceLocator();
    private UnityContainer Ioc = new UnityContainer();
 
    static ServiceLocator() { }
 
    private ServiceLocator()
    {
        // What do we want? Bootstraping!
        // When do we want it? NOW!
        Bootstrap();
    }
 
    public static ServiceLocator Instance
    {
        get
        {
            return instance;
        }
    }
 
    #endregion
 
    /// <summary>
    /// Bootstraps all registered 
    /// </summary>
    private void Bootstrap()
    {
        // Get all injected instances (objects)
        IEnumerable<Type> injectedInstances = 
                    from a in AppDomain.CurrentDomain.GetAssemblies()
                    from t in a.GetTypes()
                    where t.IsDefined(typeof(InjectAttribute), false)
                    select t;
 
        // the class type: instanceType
        foreach (Type instanceType in injectedInstances)
        {
            // get the injected attributes
            var injectAttributes = instanceType.GetCustomAttributes(
                    attributeType: typeof(InjectAttribute),
                    inherit: false)
                .Cast<InjectAttribute>();
 
            // the interface: injectAttribute.RegisteredType
            foreach (InjectAttribute injectAttribute in injectAttributes)
            {
                if (injectAttribute.LifetimeManager != null)
                {
                    Ioc.RegisterType(
                        from: injectAttribute.RegisteredType,
                        to: instanceType,
                        lifetimeManager: injectAttribute.LifetimeManager);
                }
                else
                {
                    Ioc.RegisterType(
                        from: injectAttribute.RegisteredType,
                        to: instanceType);
                }
            }
        }
    }
 
 
    public T Resolve<T>()
    {
        return Ioc.Resolve<T>();
    }
}

That's as simple as it gets. To test this concept I created one instance of IClassA and one of IClassB and populated their properties. When resolving the ClassC the constructed instances of A and B should be injected in the C constructor allowing us to print the vaules using the Check() method.

var a = ServiceLocator.Instance.Resolve<IServiceA>();
a.Message = "Hello";
 
var b = ServiceLocator.Instance.Resolve<IServiceB>();
b.Number = 150;
 
var c = ServiceLocator.Instance.Resolve<ClassA>();
c.Check();

Great!

The source code is available at GitHub, https://github.com/EricHerlitz/service-locator-singleton

Please note that this portal is a BETA site , I will continuously improve all functionality and performance during the coming weeks / the author