Home > Back-end >  C# Dependency Injection add concrete service depend on other service
C# Dependency Injection add concrete service depend on other service

Time:01-22

I have a problem with using specific service depend on other service in web api Program file. I create IDatabaseOption interface and DatabaseOptions class like this (and add values in appsettings):

public interface IDatabaseOptions
{
    string ConnectionString { get; set; }
    DatabaseType DatabaseType { get; set; }
    string DatabaseName { get; set; }
}

public class DatabaseOptions : IDatabaseOptions
{
    public string ConnectionString { get; set; }
    public DatabaseType DatabaseType { get; set; }
    public string DatabaseName { get; set; }
}

and the registration is:

services.Configure<DatabaseOptions>(configuration.GetSection(nameof(DatabaseOptions)));
services.AddSingleton<IDatabaseOptions>(serviceProvider => serviceProvider.GetRequiredService<IOptions<DatabaseOptions>>().Value);

And next step I'd like to register concrete DbContext based on DatabaseType like this:

services.AddDbContext<ApplicationDbContext>().AddOptions<DbContextOptionsBuilder>().Configure<IDatabaseOptions>((options, databaseOptions) =>
{
    switch (databaseOptions.DatabaseType)
    {
        case DatabaseType.MSSQL:
            options.UseSqlServer(databaseOptions.ConnectionString);
            break;

        case DatabaseType.POSTGRESQL:
            options.UseNpgsql(databaseOptions.ConnectionString);
            break;

        default: break;
    }
});

and at this point it not work. If I use DI in for example Repository in constructor like Repository(ApplicationDbContext), the context is not set. I don't have to use BuildServiceProvider() because it is not proper solution. How can I use registered service to decide for other service at this point?

CodePudding user response:

If you make the settings while registering the DbContext object, the problem will disappear. When I tried the following piece of code, the error you mentioned disappeared.

services.AddDbContext<ApplicationDbContext>((provider, optionsBuilder) =>
{
    var options = provider.GetRequiredService<IDatabaseOptions>();
    switch (options.DatabaseType)
    {
        case DatabaseType.MSSQL:
            optionsBuilder.UseSqlServer(options.ConnectionString);
            break;
        case DatabaseType.POSTGRESQL:
            break;
        default:
            throw new ArgumentOutOfRangeException();
    }
});
  • Related