Stephen York
Stephen York

Reputation: 1429

.NET Core Windows Service with Autofac

I've created ASP.NET Core web apps where I've used AutoFac by putting .UseServiceProviderFactory(new AutofacServiceProviderFactory()) on the Host.CreateDefaultBuilder(...)``` call as well as the following on the Startup class:

public void ConfigureContainer(ContainerBuilder builder)
{
    builder.RegisterModule<ExampleRestApiModule>();

}

I've also done it on a Console app by creating the ContainerBuilder manually then getting an instance of an App class and calling Run(). I'm writing a Windows Service in .NET Core 5 now and with the built in DI the template project registers a Worker class which derives from Microsoft.Extensions.Hosting.BackgroundService. There isn't a call directly in my project to the ExecuteAsync method so it's not like the standard console app where I manually get the instance to invoke. This is my program class:

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

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        IConfiguration configuration = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            //.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables()
            .AddCommandLine(args)
            .Build();

        return Host.CreateDefaultBuilder(args)
            .UseWindowsService(options => { options.ServiceName = "MariaDB Backup Service"; })
            .UseServiceProviderFactory(new AutofacServiceProviderFactory())
            .ConfigureServices((hostContext, services) =>
            {
                var backupServiceConfig = new List<BackupServiceConfig>();
                configuration.Bind("Tasks:BackupService", backupServiceConfig);
                services.AddSingleton(backupServiceConfig);
                
                services.AddTransient<IBackupCommandFactory, BackupCommandFactory>();
                services.AddTransient<MariaDbBackupService>();
                services.AddHostedService<BackgroundWorker>();

            })
            ;


    }
}

and I've tried putting the public void ConfigureContainer(ContainerBuilder builder) on the background worker but it's never getting called. Given that if this was a ASP.NET Core app the Host.CreateDefaultBuilder call would use:

.ConfigureWebHostDefaults(webBuilder =>
{
    webBuilder.UseStartup<Startup>();
});

and then something know to invoke the AutoFac ConfigureContainer method, is there an equivalent Use statement I'm supposed to put in so the platform knows to call it? Or is there another way to do it?

I want to use some more advanced IoC features within AutoFac and not sure how else to get the IServiceCollection integrated between AutoFac and MS DI.

Upvotes: 1

Views: 2203

Answers (2)

Andrey Bilalov
Andrey Bilalov

Reputation: 21

I would like add code sample to @alsami first suggestion.

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

        private static void RegisterDependencies(ContainerBuilder builder)
        {
            builder.RegisterModule(new MyModule());
        }

Upvotes: 1

alsami
alsami

Reputation: 9815

You need to pass the ConfigureContainer function into the call .UseServiceProviderFactory(new AutofacServiceProviderFactory(ConfigureContainer)) or you can add an additional call .ConfigureContainer<ContainerBuilder>(ConfigureContainer)

We have a sample for this here as well.

Upvotes: 2

Related Questions