Before I begin, I'm aware the Service Locator pattern is not recommended and it's better to inject services into the classes where they are used. However, I have a large legacy codebase that creates a lot of objects inside methods without DI. Refactoring this would be a monumental task so I am trying to implement a static Service Locator as reasonably as possible.
My idea is to create a scope as part of a request middleware and set the ServiceLocator instance here. Then allow it to flow through the rest of the request chain before it exists and disposes. I have tested this and my created class is disposed, so it seems to be working as expected. Are there any pitfalls I haven't considered?
public class DependencyLocatorHandler(RequestDelegate next, IServiceProvider serviceProvider)
{
public async Task InvokeAsync(HttpContext context)
{
await using var serviceProviderScope = serviceProvider.CreateAsyncScope();
ServiceLocator.SetServiceProvider(serviceProviderScope.ServiceProvider);
await next(context);
}
}
public static class ServiceLocator
{
private static IServiceProvider _serviceProvider;
public static void SetServiceProvider(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public static T GetService<T>()
{
return _serviceProvider.GetService<T>();
}
}
-
2Will not work for multithreading.Basilevs– Basilevs2025年04月23日 08:40:25 +00:00Commented Apr 23 at 8:40
-
And accessing any sort of shared state from a static context will kill you application's ability to serve multiple requests by the same user concurrently if you have IIS configured for sticky sessions.Greg Burghardt– Greg Burghardt2025年04月23日 10:57:52 +00:00Commented Apr 23 at 10:57
-
I was worried about this. But what other option do I have?Steve– Steve2025年04月23日 12:05:07 +00:00Commented Apr 23 at 12:05
-
Can you use OWIN -- is your application old enough to use that? I think the trick here is to initialize the service locator as an object at the beginning of your pipeline. Then each middleware component can pull it out of the current HTTP context.Greg Burghardt– Greg Burghardt2025年04月23日 12:22:14 +00:00Commented Apr 23 at 12:22
-
No, it's dotnet 9.Steve– Steve2025年04月23日 21:58:08 +00:00Commented Apr 23 at 21:58