ServiceLocator

ServiceLocator class is a simple implementation of a widely known Service Locator (Registry) pattern. It is used throughout OpenWaves framework to encapsulate the process of resolving dependencies.

Service resolution

ServiceLocator.Resolve<T>(), ServiceLocator.TryResolve<T>(...), and ServiceLocator.ResolveOptional<T>() methods can be used to acquire an instance of a service. See examples below.

    using OpenWaves;

    ...

    var loggingService = ServiceLocator.Resolve<ILoggingService>();   // Will throw if ILoggingService cannot be resolved

    var loggingService = ServiceLocator.ResolveOptional<ILoggingService>() ?? LoggingService.Null;

    ILoggingService loggingService;
    if (ServiceLocator.TryResolve(out loggingService))
        loggingService.LogDebug(...);

Resolvers

ServiceLocator class delegates a responsibility of resolving service instances to a resolver (a class implementing IResolver interface). Resolver to be used is specified using ServiceLocator.SetResolver(...) method. In most cases the resolver is going to be specified in Application_Start method in Global.asax.cs file. BasicResolver class is the simplest implementation of a resolver. It is a dictionary based lookup of service instances by the type of service they implement. The following example illustrates how to register services with BasicResolver and specify the resolver to be used by ServiceLocator.

    using OpenWaves;

    ...

    var resolver = new BasicResolver()
        .Register<ILoggingService>(new FileLoggingService(...))
        .Register<IAnotherService>(new AnotherServiceImplementation(...));

    ServiceLocator.SetResolver(resolver);

Very often when IoC container is used in a project, it is desirable to use it as a resolver. A container instance can easily be adapted to IResolver interface and used as a resolver. Example illustrates how AutoFac container can be adapter.

    using OpenWaves;

    ...

    public class AutoFacResolver : IResolver
    {
        private readonly IContainer container;

        public AutoFacResolver(IContainer container)
        {
            this.container = container;
        }

        public bool TryResolve<T>(out T service) where T : class
        {
            service = this.container.ResolveOptional<T>();
            return service != null;
        }
    }

Default service implementations

If the currently used resolver cannot provide an instance of a service and the service interface is decorated with DefaultImplementationAttribute, service locator will try to create an instance of a default implementation using a parameterless public constructor of a provided type.

    using OpenWaves;

    ...

    [DefaultImplementation(typeof(FileLoggingService))]
    public partial interface ILoggingService
    {
        // ...
    }

    public class FileLoggingService : ILoggingService
    {
       // ...
    {

Lifetime of services

ServiceLocator is not concerned in the lifetime of services it returns. Lifetime management is highly dependent on the implementation of a resolver. BasicResolver when used will return the instances provided during service registration. When returning default implementations, ServiceLocator will only ever create one instance of each implementation.

Last edited Jun 15, 2012 at 7:55 AM by mgrzyb, version 6

Comments

No comments yet.