Paul
Paul

Reputation: 3253

Cannot get injection to work in Azure Function when a service has other dependencies

I have a service CompanyService

This service is dependent on 2 other services - ICompanyRepository and IDataCacheService

public class CompanyService : ICompanyService
{
    private readonly ICompanyRepository _companyRepository;
    private IDataCacheService _dataCacheService;

    public CompanyService(ICompanyRepository companyRepository, IDataCacheService dataCacheService)
    {
        _companyRepository = companyRepository;
        _dataCacheService = dataCacheService;
    }
}

This services themselves have no dependencies

Now I need to make this available via the built in injection within my Azure Function

so in Startup.cs, I modified Configure to add the new services

public override void Configure(IFunctionsHostBuilder builder)
{
    var cosmosDbConnectionString = new CosmosDBConnectionString(Environment.GetEnvironmentVariable("CosmosDBConnection"));
    builder.Services.AddSingleton<IDocumentClient>(s =>
       new DocumentClient(cosmosDbConnectionString.ServiceEndpoint, cosmosDbConnectionString.AuthKey));

    var companyRepository = new CompanyRepository();
    builder.Services.AddSingleton<ICompanyRepository>(companyRepository);

    var dataCacheService = new DataCacheService();
    builder.Services.AddSingleton<IDataCacheService>(dataCacheService);

    var companyService = new CompanyService(companyRepository, dataCacheService);

    builder.Services.AddSingleton<ICompanyService>(companyService);
}

This compiles and runs through fine

However, when I add ICompanyService as a parameter of my function I get the error

Cannot bind parameter 'companyService' to type ICompanyService

My method is below

public class Companies
{
    private const string OperationName = "OPERATION";

    [FunctionName(OperationName)]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "myroute/")]HttpRequest req,
        ICompanyService companyService,
        ILogger log)
    {
       //logic here
    }
}

This is the same way as other function run methods within my project

What have I done wrong?

This also doesn't work with the standard AddSingleton syntax

builder.Services.AddSingleton<ICompanyService, CompanyService>();

Paul

Upvotes: 1

Views: 324

Answers (1)

Nkosi
Nkosi

Reputation: 247088

Given the shown configuration, the registration can be simplified to

public override void Configure(IFunctionsHostBuilder builder) {
    var services = builder.Services;
    var cosmosDbConnectionString = new CosmosDBConnectionString(Environment.GetEnvironmentVariable("CosmosDBConnection"));
    services.AddSingleton<IDocumentClient>(s =>
       new DocumentClient(cosmosDbConnectionString.ServiceEndpoint, cosmosDbConnectionString.AuthKey));

    services.AddSingleton<ICompanyRepository, CompanyRepository>();        
    services.AddSingleton<IDataCacheService, DataCacheService>();    
    services.AddSingleton<ICompanyService, CompanyService>();
}

All that is left is to make sure to explicitly inject the required service into the function instance via constructor injection.

public class Companies {
    private const string OperationName = "OPERATION";
    private readonly ICompanyService companyService;

    public Companies(ICompanyService companyService) {
        this.companyService = companyService;
    }

    [FunctionName(OperationName)]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "myroute/")]HttpRequest req,
        ILogger log) {
       //logic here
    }
}

Reference Use dependency injection in .NET Azure Functions

Upvotes: 2

Related Questions