When it comes to injecting dependencies into static classes, we encounter a fundamental limitation: the scope and lifetime of static classes are independent of the main application thread, means that by the time the dependency injection (DI) is registered in the application, static classes have already been initialized in memory, static classes are initialized before our application entry point has even started.
  • We should reserve static classes for functionalities that don't require configuration, such as utility functions.
  • For functionalities that involve business logic and require dependencies, we have two options:
    • Option 1: Convert the static class to an instance class and supply the dependency through Constructor Injection. This allows us to create instances of the class with different dependencies, making it more flexible and testable.
    • Option 2: Supply the dependency to the class's public method through Method Injection, this involves passing the dependency as a parameter to the method whenever it's called. While this approach maintains the static nature of the class, it may lead to less maintainable code and can become complicated with multiple dependencies.

Ultimately, our choice between these options depends on the specific requirements of our application.

To inject a dependency into a static class in C#, we need to carefully consider the design and use of the static class, as static classes do not support constructor injection like regular classes, as we told you one common approach is to use a technique called "method injection," where we pass the dependency as a parameter to the static method.

Example:

Let's say we have a static class named Logger that needs a dependency on an ILogger interface.


    public interface ILogger
    {
        void Log(string message);
    }

    public static class Logger
    {
        private static ILogger _logger;

        public static void Initialize(ILogger logger)
        {
            _logger = logger;
        }

        public static void LogMessage(string message)
        {
            if (_logger != null)
            {
                _logger.Log(message);
            }
            else
            {
                // Handle the case where the logger hasn't been initialized
                Console.WriteLine("Logger not initialized. Logging to console: " + message);
            }
        }
    }
    

In above example, we have a static class Logger with a private static field _logger of type ILogger and also have a static method Initialize to set the logger instance, and a static method LogMessage to log messages.

Now to inject the dependency into the Logger class, we first need to create a class that implements the ILogger interface:


    public class FileLogger : ILogger
    {
        public void Log(string message)
        {
            // Code to log message to a file
        }
    }
    

Now, we can initialize the Logger class with an instance of FileLogger using the Initialize method:


    Logger.Initialize(new FileLogger());
    

After initialization, we can use the LogMessage method to log messages:


    Logger.LogMessage("This is a log message.");
    

Using above step, we can successfully injected a dependency into a static class in C# using method injection.

2

Using Dependency Injection in a Static Class in C# with an example

Let's consider a scenario where we have a static class named DoctorService that needs a dependency on a IDoctorRepository interface for fetching doctor details from a database.

In this example, we have a static class DoctorService with a private static field _doctorRepository of type IDoctorRepository, also have a static method Initialize to set the doctor repository instance, and a static method GetDoctor to fetch doctor details.


    public class Doctor
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Specialization { get; set; }
    }

    public interface IDoctorRepository
    {
        Doctor GetDoctorById(int id);
    }

    public class DoctorRepository : IDoctorRepository
    {
        public Doctor GetDoctorById(int id)
        {
            // Code to fetch doctor details from database
            return new Doctor { Id = id, Name = "Dr. John Doe", Specialization = "Cardiologist" };
        }
    }

    public static class DoctorService
    {
        private static IDoctorRepository _doctorRepository;

        public static void Initialize(IDoctorRepository doctorRepository)
        {
            _doctorRepository = doctorRepository;
        }

        public static Doctor GetDoctor(int id)
        {
            if (_doctorRepository != null)
            {
                return _doctorRepository.GetDoctorById(id);
            }
            else
            {
                // Handle the case where the doctor repository hasn't been initialized
                return null;
            }
        }
    }
    

Now, let's configure dependency injection using the built-in Dependency Injection container in a .NET Core or .NET 5+ application:


    // ConfigureServices method in Startup.cs
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton();
    }
    

With this configuration, the DoctorRepository will be registered as a singleton instance of IDoctorRepository.

In next, step we need to initialize the DoctorService class with an instance of IDoctorRepository in our application startup:


    // Startup.cs or Program.cs
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // Other configurations

        // Initialize DoctorService class with DoctorRepository instance
        DoctorService.Initialize(app.ApplicationServices.GetRequiredService());
    }
    

After initialization, we can use the DoctorService class to get doctor details:

    var doctor = DoctorService.GetDoctor(1);
    

So now we have successfully used dependency injection in a static class in C# by using  the built-in Dependency Injection container.

3

If you really want to use dependency injection in a static class, you can try this approach. When it comes to using dependency injection in a static class in C#, we face a challenge because static classes don't support constructor injection like regular classes. However, we can still achieve dependency injection by using the singleton pattern along with dependency injection containers.

Example:

Let's consider a scenario where we have a static class named Settings that needs a dependency on a ISettingsProvider interface.


    public interface ISettingsProvider
    {
        string GetSetting(string key);
    }

    public class SettingsProvider : ISettingsProvider
    {
        public string GetSetting(string key)
        {
            // Code to fetch setting from configuration files, database, etc.
            return "Value for " + key;
        }
    }

    public static class Settings
    {
        private static ISettingsProvider _settingsProvider;

        public static void Initialize(ISettingsProvider settingsProvider)
        {
            _settingsProvider = settingsProvider;
        }

        public static string GetSetting(string key)
        {
            if (_settingsProvider != null)
            {
                return _settingsProvider.GetSetting(key);
            }
            else
            {
                // Handle the case where the settings provider hasn't been initialized
                return "Default value";
            }
        }
    }
    

In this example, we have a static class Settings with a private static field _settingsProvider of type ISettingsProvider. We also have a static method Initialize to set the settings provider instance, and a static method GetSetting to fetch settings.

Now, let's configure dependency injection using the built-in Dependency Injection container in a .NET Core or .NET 5+ application:


    // ConfigureServices method in Startup.cs
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton();
    }
    

With this configuration, the SettingsProvider will be registered as a singleton instance of ISettingsProvider.

Next, we need to initialize the Settings class with an instance of ISettingsProvider in our application startup:


    // Startup.cs or Program.cs
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // Other configurations

        // Initialize Settings class with SettingsProvider instance
        Settings.Initialize(app.ApplicationServices.GetRequiredService());
    }
    

After initialization, we can use the Settings class to get settings:


    var settingValue = Settings.GetSetting("Key");