Search code examples
c#windows-services.net-6.0

NET 6: Windows Service with strongly typed configuration


I'm trying to create a Windows Service using NET 6 and documentation found here.

I'd like to use strongly typed configuration pattern, so I modified startup code this way:

using IHost host = Host.CreateDefaultBuilder(args)
    .UseWindowsService(options =>
    {
        options.ServiceName = "My Service";
    })
    .ConfigureAppConfiguration((hostingContext, configuration) =>
    {
        configuration.Sources.Clear();
        IHostEnvironment env = hostingContext.HostingEnvironment;

        configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
    })
    .ConfigureServices((hostingContext, services) =>
    {
        services.AddSingleton<MyService>();
        services.Configure<AppSettings>(hostingContext.Configuration.GetSection("AppSettings"));
        services.AddHostedService<WindowsBackgroundService>();
    })
    .Build();

await host.RunAsync();

Then in MyService.cs:

private AppSettings _appSettings;

public MyClass(AppSettings appSettings)
{
    _appSettings = appSettings;
}

This gives me the following exception:

System.InvalidOperationException: 'Unable to resolve service for type 'StatSveglia.Service.AppSettings' while attempting to activate 'StatSveglia.Service.SvegliaService'.'

It seems that this line has no effect:

services.Configure<AppSettings>(hostingContext.Configuration.GetSection("AppSettings"));

How should I change my code to use configuration injection?

A side question: in the example service found in documentation, services.AddHttpClient<JokeService>(); is used to add the service. My service is not an HTTP client, so I preferred .AddSingleton<>. Is this a good choice?


Solution

  • After further reading I found out that the line:

    services.Configure<AppSettings>(hostingContext.Configuration.GetSection("AppSettings"));
    

    registers for dependency injection the class IOptions<AppSettings> and not AppSettings itself.

    The correct use is therfore:

    private IOptions<AppSettings> _appSettings;
    
    public MyClass(IOptions<AppSettings> appSettings)
    {
        _appSettings = appSettings;
    }
    
    private void SomeMethod()
    {
        var mySetting = _appSettings.Value.MySetting
    }