Home > front end >  Unable to resolve dead simple configuration dependency
Unable to resolve dead simple configuration dependency

Time:05-18

I am trying to set up dependency injection in a small blazor-based web app.

My current code is:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();

AddDeliveryStats(builder.Services, builder.Configuration);

// ...blazor template things...

void AddDeliveryStats(IServiceCollection services, ConfigurationManager config)
{
    services.Configure<BigQuerySettings>(config.GetSection("BigQuery"));
    services.AddTransient<IBigQueryClient, BigQueryClient>();
    // ...other stuff not pertinent to the error...
}

where BigQuerySettings is given as

public class BigQuerySettings
{
    public string ProjectId { get; set; }
    public string DataSetId { get; set; }
    public string AuthFilePath { get; set; }
}

and BigQueryClient has the following constructor:

public BigQueryClient(
    BigQuerySettings bigQuerySettings,
    ILogger<BigQueryClient> logger) { /* ... */ }

and my appsettings.json contains the following:

{
  // ...
  "BigQuery": {
    "ProjectId": "<project-identifier>",
    "DataSetId": "",
    "AuthFilePath": "BigQueryAuthProd.json"
  }
}

and if this looks pretty much like a tutorial example, that's because it basically is. It does not work and it is not obvious why. I get the following error:

Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: IBigQueryClient Lifetime: Transient ImplementationType: BigQueryClient': Unable to resolve service for type 'BigQuerySettings' while attempting to activate 'BigQueryClient'.)

I have copied this code from online tutorial examples and adapted it as appropriate to my own classes, and I have read every piece of documentation I have been able to find (much of which I can't understand) and googled at least ten different permutations of the keywords in the error message. Nothing really points to what I am doing wrong.

CodePudding user response:

By default, a call to services.Configure will only allow injecting an IOption<BigQuerySettings> into your consumers.

If, however, you wish to inject BigQuerySettings directly into your consumer (which I would argue you should), you should do the following:

BigQuerySettings settings =
    Configuration.GetSection("BigQuery").Get<BigQuerySettings>();

// TODO: Verify settings here (if required)

// Register BigQuerySettings as singleton in the container.
services.AddSingleton<BigQuerySettings>(settings);

This allows BigQuerySettings to be injected into BigQueryClient.

CodePudding user response:

Following the advice of Steven, I used ServiceCollection.AddScoped to resolve the problem:

services.AddScoped(_ => config.GetSection("BigQuery").Get<BigQuerySettings>());
  • Related