Search code examples
c#dependency-injectioninversion-of-controlioc-containerasp.net-core-2.1

how to configure dependencies in asp.net core


I have an ASP.Net Core 2.1 application. I need to register & inject few dependencies of AWS.

Currently, the implementation looks like this:

public abstract class BaseService
{
    protected readonly IConfiguration _configuration;
    protected readonly RegionEndpoint _region;
    protected readonly IAmazonDynamoDB _dynamoClient;
    protected  IPocoDynamo _pocoDynamo;

    public BaseService(IConfiguration configuration)
    {
        _configuration = configuration;
        var awsSettings = configuration.GetSection("AWS");
        _dynamoClient = SetDynamoClient(awsSettings);
        _pocoDynamo = SetPocoDynamoClient();
    }

    protected IAmazonDynamoDB SetDynamoClient(IConfigurationSection configuration)
    {
        AWSCredentials credentials = new BasicAWSCredentials(configuration["AccessKey"], configuration["AccessSecret"]);
        return new AmazonDynamoDBClient(credentials, _region);
    }

    protected IPocoDynamo SetPocoDynamoClient()
    {
        return new PocoDynamo(_dynamoClient);
    }
}

While unit testing, AWS services can't be mocked due to this.

I want to register all these dependencies in Startup.cs in ConfigureServices()

This is what I was trying:

public void ConfigureServices(IServiceCollection services)
{
    AWSCredentials credentials = new BasicAWSCredentials(configuration["AccessKey"], configuration["AccessSecret"]);

    services.AddTransient(IAmazonDynamoDB, (a) =>
         {
             return new AmazonDynamoDBClient(credentials, RegionEndpoint.GetBySystemName(""))
         });
    // here I need to pass the IAmazonDynamoDB to below IOC
    // services.AddSingleton<IPocoDynamo,new PocoDynamo()> ();

    return services;
}

But this is throwing an error

Error CS0119 'IAmazonDynamoDB' is a type, which is not valid in the given context

How to configure dependencies as required here?

Thanks!


Solution

  • Use factory delegate to call the registered service

    public void ConfigureServices(IServiceCollection services) {
        AWSCredentials credentials = new BasicAWSCredentials(configuration["AccessKey"], configuration["AccessSecret"]);
        services.AddTransient<IAmazonDynamoDB>(sp => 
            new AmazonDynamoDBClient(credentials, RegionEndpoint.GetBySystemName(""))
        );
    
        //here pass the IAmazonDynamoDB to below IOC
        services.AddSingleton<IPocoDynamo>(serviceProvider => {
            var pocoDynamo = new PocoDynamo(serviceProvider.GetRequieredService<IAmazonDynamoDB>());
            pocoDynamo.SomeMethod();
            return pocoDynamo;
        });
    }
    

    The target class should no longer need to be dependent on IConfiguration as the dependencies can be explicitly injected via constructor injection.

    public abstract class BaseService {
        protected readonly IAmazonDynamoDB dynamoClient;
        protected readonly IPocoDynamo pocoDynamo;
    
        public BaseService(IAmazonDynamoDB dynamoClient, IPocoDynamo pocoDynamo) {        
            this.dynamoClient = dynamoClient;
            this.pocoDynamo = pocoDynamo;
        }
    }