Enqueue Job from Assembly that Does not have a Reference to the Method being Enqueued

We are trying to isolate dependencies for both code management and licensing purposes. We have a third-party licensed component that we want to run only in our hangfire Windows service instances. We need to Enqueue a static method that will do the work called MyNameSpace.MyAssembly.Foo(Int32 SomeId) from our Web application but we do not want the web application to have to have a reference to MyNameSpace.MyAssembly as it would then require references to the third-party component and licensing fees. The 2 ways we thought to implement would be to put an IIS site on the same server as the Hangfire server hosting just an API that is called to enqueue or create an intermediate FooJob table that the website submits to directly and then have a Hangfire job poll based on a defined Cron Schedule. I am hoping there is a better way than the 2 we thought of as they have their own downsides. Thanks.

The simplest method is to wrap such a job with some interface in a shared assembly both projects have access to. You will create background jobs based on this interface, while the actual implementation will be substituted at run-time using dependency injection. Consider you have the following interface:

public interface ISharedServices
{
    void Foo();
}

Now you can create background jobs using this interface in any projects that have reference to its assembly:

BackgroundJob.Enqueue<ISharedServices>(x => x.Foo());

And only in a Windows Service project you define an implementation for this interface and bind it using an IoC container integration you are probably using in your project:

public class MySharedServices : ISharedServices
{
    public void Foo() { SomeStaticClass.Foo(); }
}

For the Microsoft.Extensions.DependencyInjection package, Hangfire integration with its DI is defined in the Hangfire.NetCore package, and we can bind interface to its implementation in the following way when configuring other services as well:

services.AddSingleton<ISharedServices>(x => new MySharedServices());

And after doing these steps, Hangfire will fetch background job based on interface, but worker will resolve and run the implementation.

1 Like