ASP.NET Core
Dependency Injection
Static Factory Class
Web Development
Programming

Accessing ASP.NET Core DI Container From Static Factory Class

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD

In ASP.NET Core, dependency injection (DI) is a fundamental concept that helps in achieving loosely coupled, manageable, and testable code. However, accessing the DI container directly from a static method or class — typically considered an anti-pattern — can sometimes be necessary. This article explores how to interact with the ASP.NET Core DI container from a static factory class while maintaining a maintainable and testable codebase.

Understanding the Basics: ASP.NET Core DI and Static Classes

ASP.NET Core comes with a built-in DI container that supports constructor injection by default. The framework handles the lifecycle of the dependencies it injects, but when dealing with static classes or methods, direct construction-based dependency injection is not possible since static methods cannot accept instance-level injections.

Using static classes generally means:

  • They do not maintain state.
  • They cannot implement interfaces or inherit from other classes.

Despite these limitations, there might be scenarios (like legacy system integration or third-party library constraints) where accessing services from a static context is required.

Accessing DI Container from Static Context

To obtain services from the DI container in a static method, the usual approach is to use a service locator pattern. This pattern involves resolving dependencies at runtime rather than at compile time. Here’s how to implement it:

  1. Service Locator Setup:
    • Create a static class that will act as a bridge to the service provider.
    • Store a reference to the IServiceProvider.
csharp
1public static class ServiceLocator
2{
3    private static IServiceProvider _serviceProvider;
4
5    public static void SetServiceProvider(IServiceProvider serviceProvider)
6    {
7        _serviceProvider = serviceProvider;
8    }
9
10    public static T GetService<T>()
11    {
12        return _serviceProvider.GetService<T>();
13    }
14}
  1. Configure Services and Register the Service Locator:
    • During the app startup, specifically in the ConfigureServices method of the Startup.cs, ensure all services are registered.
    • Set the service provider to your ServiceLocator.
csharp
1public void ConfigureServices(IServiceCollection services)
2{
3    // Add services
4}
5
6public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
7{
8    ServiceLocator.SetServiceProvider(app.ApplicationServices);
9}
  1. Usage From a Static Method:
csharp
1public static class StaticFactory
2{
3    public static void CallSomeService()
4    {
5        var myService = ServiceLocator.GetService<IMyService>();
6        myService.PerformAction();
7    }
8}

Risks and Considerations

  • Tight Coupling: Use of the service locator pattern can lead to hidden dependencies, making the system more difficult to maintain and test.
  • Testing Challenges: Testing static methods that use service locator can be difficult, often requiring the setup of the entire service container.
  • Design Smell: Overutilizing this approach might indicate a design issue in your application architecture.

Best Practices

  • Limit Usage: Restrict the use of static methods for service location to scenarios where it’s genuinely required.
  • Abstraction: Encapsulate the logic of locating and retrieving services, which aids in isolation and maintains a single point of modification.
  • Documentation: Clearly document the reasons and mechanisms for using a service locator in static contexts to assist future maintainers.

Summary Table

ConcernDetail
CouplingIncreases coupling, leading to maintenance challenges.
TestabilityMakes unit testing harder due to hidden dependencies and requirement for full context.
DesignOften a symptom of design issues requiring reevaluation of application architecture.
Usage RecommendationUse sparingly and only when necessary, with documented justification.

In conclusion, while accessing the ASP.NET Core DI container from a static factory class is possible using the service locator pattern, it should be done with caution. Always consider potential design alternatives and aim for a loosely coupled architecture to facilitate easier testing and maintenance.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Object-Oriented Design practice on Codemia

Turn requirements into classes, and defend the design, on the problems that come up in OOD rounds.

Practice OOD