Search code examples
c#.net-coreautofac

How to Inject IHostedService in Dependecy injection from Autofac Module


I am trying to use Autofac Di container to build dependencies instead of .netcore default IServiceCollection. I Need to inject IHostedService. IServiceCollection has method AddHostedService but I can not find alternative method in Autofac ContainerBuilder.

Autofac Documentation says that you can populate ContainerBuilder from IServiceCollection so one solution would be to add IHostedService in IServiceCollection and then populate ContainerBuilder from it but I have multiple AutofacModule, some of them registering each other and they each have responsibility for their services and to inject some service from ChildModule directly in Startup does not seem right.

 public class ParentModule : Module
 {
    protected override void Load(ContainerBuilder builder)
    {
       builder.RegisterModule(new ChildModule());
    }
 }

 public class ChildModule : Module
 {
    protected override void Load(ContainerBuilder builder)
    {
       //TODO Add hosted service here.
    }
 }

 public class Startup
 {
   ...
   ...
   public IServiceProvider ConfigureServices(IServiceCollection services)
   {
      var container = new ContainerBuilder();
      container.RegisterModule(new ParentModule());

      return new AutofacServiceProvider(container.Build());
   }
   ...
   ...
 }

Eventually I want to pack ParentModule in package and upload it in custom NugetServer so i can just add ParentModule wherever i need it without remembering to inject some services in IServiceCollection.

My modules are much complex and on multiple level depth so simple extension method for IServiceCollection to add additional dependencies is not an option.


Solution

  • Just register them like this

    builder.RegisterType<MyHostedService>()
           .As<IHostedService>()
           .InstancePerDependency();
    

    The host (web-host or regular host) takes care of resolving all those registrations of IHostedService and runs them.

    The extension method AddHostedService<THostedService> doesn't do anything different as you can see

    public static IServiceCollection AddHostedService<THostedService>(this IServiceCollection services)
    where THostedService : class, IHostedService
    {
       return services.AddTransient<IHostedService, THostedService>();
    }
    

    You can find the source-code on github.

    UPDATE 2022-03-15

    As pointed out in the comments, the MS registration is using singletons now. While it technically doesn't matter for this specific case, if you want to align it with the MS registration, you would need to do the following

    builder.RegisterType<MyHostedService>()
           .As<IHostedService>()
           .SingleInstance();