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>());