Introduction

With the new previews of dotnetcore there are new project templates. The new “worker” project template is the one which is being aimed at new microservices which need to run background processes or monitor processing on a queue etc.

On investigating I was curious to how to register services and if you’re used to ASP.Net Core then this should be straight forward, or is it?

Registering Services

The whole ethos, as far as I can make out, is the “hosting” model has been brought together and everything just uses a “host”. There is a web specific setup extension method but still an IHost. Let’s take a quick look at the ASP.NET Core 3 program.cs contents.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

As you can see this uses the new Host builder, however there is the familier UseStartup<Startup> style registration inside the ConfigureWebHostDefaults method that has been present for a few versions now.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });
}

The “Worker” host builder looks familar but also different. Instead of registering a Startup class and having a ConfigureServices method declared the functionality is directly on the IHostBuilder. This is how you register required services for your BackgroundService.

The delegate required for this method is …

Action<HostBuilderContext, IServiceCollection> configureDelegate

… which allows services to be registered.

Simple Example

Using the IClock abstraction I wrote about in Mocking the Clock this would be registered as follows …

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureServices((hostContext, services) =>
        {
            services.AddSingleton<IClock, Clock>();  
            services.AddHostedService<Worker>();
        });

The default Worker class can then request the IClock dependency through constructor injection and update the usage of the DateTimeOffset.Now call from the default example as follows. Including the full worker class below to show full usage of the dependencies.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    private readonly IClock _clock;

    public Worker(ILogger<Worker> logger, IClock clock)
    {
        _logger = logger;
        _clock = clock;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}", _clock.UtcNow);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

Conclusion

In this post we’ve looked briefly at the host builder changes between ASP.NET Core 2.2 and DotNet Core 3 (Preview 6) Worker host builder and how to register services onto the IServiceCollection to allow for them to be used in the worker through dependency injection.

Any questions/comments then please contact me on Twitter @WestDiscGolf