Hangfire cannot find registered service on external assembly


#1

I have an issue with Hangfire, most likely because of my ignorance about some topics.

I have a host/plugins infrastructure, where each plugin is loaded at runtime and it register its interfaces.

public void ConfigureServices(IServiceCollection services, IConfigurationRoot Configuration)
{
    services.AddTransient<IManager, Manager>();
    services.AddTransient<IAnotherManager, AnotherManager>();

    this.AddControllers(services);            
}

Some plugin may add jobs using Hangfire, which are also set during runtime

public void ScheduleJobs() 
{
   RecurringJob.AddOrUpdate<IManager>(n => n.SayHello(), Cron.Monthly);
}

The issue I have is, while any service registered directly in the host is correctly resolved in hangfire, all the interfaces (ex IManager) that are defined in external assemblies aren’t found.

I added a customer JobActivator where I’m passing the IServiceCollection and I can actually see that those external services are registered (and I can use them anywhere else but from Hangfire), but still in the JobActivator, when Hangfire tries to resolve the external service, it fails.

public override object ActivateJob(Type type)
{
    // _serviceCollection contains the IManager service
    var _provider = _serviceCollection.BuildServiceProvider();
    
    // this will throw an Exception => No service for type '[...].IManager' has been registered.
    var implementation = _provider.GetRequiredService(type);
    return implementation;
}

In the same example, if I use the Default JobActivator, then the exception I get is System.MissingMethodException: Cannot create an instance of an interface.

I could enqueue the job using the Class instead of the Interface, but that’s not the point and anyway if the Class has services injected, those will not be resolved as well.

What am I missing?


#2

Update:

If instead of getting the serviceCollection in the JobActivator I get the serviceProvider, the result is the same: I can see in the service provider that the service is registered, but GetRequiredService throws anyway an exception

public class ServiceProviderJobActivator : JobActivator
{
    private IServiceProvider _serviceProvider;

    public ServiceProviderJobActivator(
        IServiceProvider serviceProvider
    )
    {
        _serviceProvider = serviceProvider;
    }

    public override object ActivateJob(Type type)
    {
        /* 
         serviceProvider contains my external service
         but still GetRequiredService throws an exception
        */
        var implementation = _serviceProvider.GetRequiredService(type);
        return implementation;
    }
}