Search code examples
c#asp.net.netdependency-injectioncastle-windsor

Is it possible to register class with private constructor to Dependency Injection


There is a class with private constructor, and the only way to get instances of that class is to call static method CreateInstance().

Is it possible to add this class to DI and how?

I am using the Castle Windsor framework for Dependency Injection.

public class Example
{
    private readonly DbContext _dbContext;

    private Example(DbContext dbContext){
        _dbContext = dbContext;  
    }
    
    public static async Task<Example> CreateInstance(DbContextProvider<DbContext> provider){
        return new Example(await provider.GetDbContextAsync());
    }
}

Solution

  • According to user Ralf's comments, it's ideal to use the AddTransient<T> (or AddScoped<T>, AddSingleton<T> depending on what you want to achieve) overload registration method that takes a delegate. As a delegate you can call your static "factory" method and in this way the dependecy injection system will create a Example instance. Note that your factory method returns a Task. You need to make sure how your dependency injection system handles such delegates. You may need to do all the registration asynchronously, or wait (e.g. wait()) for a Task from a factory method.

    services.AddTransient<Example>(_ => CreateInstance(provider))
    

    Additionally...

    You can also "cover" all this mechanics with the help of Extension Methods, in order to provide a clean and simple API. Your Example class could then be internal and only the be a registration extension-method would be public. Keep in mind, however, that it also strongly depends on the structure of your project. Simple example:

    // Extensions method class
    public static IServiceCollectionExtensions
    {
        public static IServiceCollection AddExample(this IServiceCollection services)
        {
           // Resolve your DbContextProvider here via IServiceCollection
           return services.AddTransient<Example>(_ => CreateInstance(provider))
        }
    }
    
    // The place you register the services
    services.AddExample()