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;
}
}
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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP