Mihaimyh
Mihaimyh

Reputation: 1410

How to configure Action<T> with dependency injection

I am trying to learn how Action<T> and Func<T> are working, for this I've created a base class which requires an Action<AppConfiguration> in it's constructor among other dependencies:

public abstract class GenericOracleTDRRepository<T> : IGenericTDRRepository<T>
{
        protected GenericOracleTDRRepository(ILogger<GenericOracleTDRRepository<T>> logger,
                                             Action<AppConfiguration> configuration,
                                             IUpdateSqlStringGenerator<T> generator)
        {
            if (configuration is null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            Logger = logger ?? throw new ArgumentNullException(nameof(logger));
            configuration(AppSettings);
            _generator = generator ?? throw new ArgumentNullException(nameof(generator));
        }

      public AppConfiguration AppSettings { get; private set; } = new AppConfiguration();
}



public class RmesgOracleReposityory : GenericOracleTDRRepository<RMesg>, IGenericTDRRepository<RMesg>
{
    public RmesgOracleReposityory(ILogger<RmesgOracleReposityory> logger,
                                  Action<AppConfiguration> appSettings,
                                  IUpdateSqlStringGenerator<RMesg> generator) : base(logger, appSettings, generator)
    {
        Logger = logger;
    }

    public new ILogger<RmesgOracleReposityory> Logger { get; }
}

I am configuring it in my DI container:

services.AddScoped<IGenericTDRRepository<RMesg>, RmesgOracleReposityory>();
services.AddTransient<IUpdateSqlStringGenerator<RMesg>, UpdateSqlStringGenerator<RMesg>>();

I am not sure where and how should I pass a valid Action<AppConfiguration> for this object?

Upvotes: 2

Views: 1450

Answers (1)

mm8
mm8

Reputation: 169330

You need to define the Action<AppConfiguration> to use somewhere.

If you for example define it in the Startup class, you could use the overload of AddScoped that accepts an IServiceProvider to resolve the other dependencies and inject it like this:

void TheAction(AppConfiguration appConfiguration) { }

services.AddScoped<IGenericTDRRepository<RMesg>, RmesgOracleReposityory>(serviceProvider =>
{
    var logger = serviceProvider.GetRequiredService<ILogger<RmesgOracleReposityory>>();
    var generator = serviceProvider.GetRequiredService<IUpdateSqlStringGenerator<RMesg>>();
    return new RmesgOracleReposityory(logger, TheAction, generator);
});

You might also define it in the RmesgOracleReposityory class and pass it to the base class' constructor:

public class RmesgOracleReposityory : GenericOracleTDRRepository<RMesg>, IGenericTDRRepository<RMesg>
{
    public RmesgOracleReposityory(ILogger<RmesgOracleReposityory> logger,
                                  IUpdateSqlStringGenerator<RMesg> generator) 
        : base(logger, TheAction, generator)
    {
        Logger = logger;
    }

    private void TheAction(AppConfiguration appConfiguration) { }

    public new ILogger<RmesgOracleReposityory> Logger { get; }
}

An Action<T> just encapsulates a void method that takes a single parameter of type T.

Upvotes: 2

Related Questions