TransWikia.com

Service locator implicit request scopes

Stack Overflow Asked by filur on November 10, 2021

I’ve created a small service locator which I will use in ActionFilterAttributes and IHttpModules. At the time of Writing I’m using simple injector, but I want to make it container agnostic. The idea is to let consumers of my framework inject an optional configuration to my classes, e.g:

container.RegisterInstance<IConfiguration>(() => new CustomConfiguration());

Below is my current draft. Please feel free to suggest any improvements. A thing that came to mind is how well it will treat a service with scoped lifestyle. For example, if I request a service in a filter’s OnActionExecuting, will the container understand that the service is requested in a web request scope, or do I have to explicitly create a scope? The configuration will be a singelton so that won’t be a problem with that specific dependency, just asking out of curiosity.

public class ServiceLocator
{
    public static T GetService<T>()
    {
        return (T)GetDependencyScope().GetService(typeof(T));
    }

    private static IDependencyScope GetDependencyScope()
    {
        if (HttpContext.Current.Items["MS_HttpRequestMessage"] is HttpRequestMessage httpRequestMessage)
        {
            return httpRequestMessage.GetDependencyScope();
        }
        return GlobalConfiguration.Configuration.DependencyResolver;
    }
}

One Answer

I would inject an instance of IServiceProvider in the IoC container you are using.

This examples shows how to do it with Simple Injector:

public class SimpleInjectorServiceProvider : IServiceProvider {

    private readonly Container container;

    public SimpleInjectorServiceProvider(Container container) {
        this.container = container;
    }

    public object GetService(Type t)
    {
        return container.GetInstance(t);   
    }
    //all other useful methods are provided by Extensions Methods in Microsoft.Extensions.DependencyInjection.Abstractions.dll

}

//Register your dependencies here
public static void RegisterContainer(Container container) {
   container.Register(typeof(IServiceProvider),() => new SimpleInjectorServiceProvider(container), Lifestyle.Singleton);
   //your dependencies
}

//use your service locator
public class AClass {
     private readonly IServiceProvider serviceProvider;
     public AClass(IServiceProvider serviceProvider) {
         this.serviceProvider = serviceProvider;
     }

     public object AMethod() {
          AType myDependency = serviceProvider.GetService<AType>();
         ...
     }
}

when switching to another DI system you just have to create another implementation of IServiceProvider

public class LightInjectServiceProvider : IServiceProvider {

    private readonly ServiceContainer container;

    public LightInjectServiceProvider(ServiceContainer container) {
        this.container = container;
    }

    public object GetService(Type t)
    {
        return container.GetInstance(t);   
    }
    //all other useful methods are provided by Extensions Methods in Microsoft.Extensions.DependencyInjection.Abstractions.dll

}

and since the "consumers" only know the interface IServiceProvider you don't need any other change

Answered by ddfra on November 10, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP