Hello,
My Question
When performing a background job, how does Hangfire know exactly which concrete class to use for performing a job? FYI, this is not documented – that is, enqueuing a job when all you know about is the interface
that has a particular instance method.
NOTE: If the solution to this question is documented, would someone please be so kind as to point me to the link? Thank you.
The Situation
Let’s go back to the EmailSender
class from the documentation – but, this time, it implements an IEmailSender
interface. Let’s suppose the definition of the IEmailSender
interface is such:
public interface IEmailSender
{
void Send(int userId, string message);
}
Listing 1. The definition of the IEmailSender
interface.
Let’s suppose that a concrete class, EmailSender
, implements the IEmailSender
interface, and is defined thus:
public class EmailSender : IEmailSender
{
public void Send(int userId, string message)
{
var dbContext = new DbContext();
var emailService = new EmailService();
// Some processing logic
}
}
Listing 2. The definition of the 'IEmailSender` class.
Now, let me create a C# Windows Service project in VS2022, and name it MyEmailingService
, that sends emails. The EmailWindowsService
class is derived from System.ServiceProcess.ServiceBase
, and I am writing my Windows Service using .NET Framework 4.8.
Now, I install Hangfire.Core
and Hangfire.SqlServer
into my project, using the Package Manager Console of VS2022. I implement my EmailWindowsService
class thusly:
using System.ServiceProcess;
using Hangfire;
using Hangfire.SqlServer;
namespace MyEmailingService
{
public partial class EmailWindowsService : ServiceBase
{
private BackgroundJobServer _server;
public EmailWindowsService()
{
InitializeComponent();
GlobalConfiguration.Configuration.UseSqlServerStorage("connection_string");
}
protected override void OnStart(string[] args)
{
_server = new BackgroundJobServer();
}
protected override void OnStop()
{
_server.Dispose();
}
}
}
Listing 3. The definition of the EmailWindowsService
class.
Of course, connection_string
is just a placeholder for the actual connection string I am utilizing. Let’s pretend that it has the correct information in it that is needed to connect to a SQL Server database.
Suppose that the .csproj that contains my EmailWindowsService
only can reference a EmailSenders.Interfaces.csproj
project in my Solution that exposes the IEmailSender
interface. If I have circular references, then I cannot refer to the concrete class, EmailSender
, that implements that interface. Okay, now I enqueue a background job in my OnStart()
method:
protected override void OnStart(string[] args)
{
_server = new BackgroundJobServer();
BackgroundJobServer.Enqueue<IEmailSender>(x => x.Send(13, "Hello"));
}
Listing 4. The definition of the OnStart
method, with the enqueuing of a background job added.
My question, again, is: I’ve passed IEmailSender
, not the concrete class, EmailSender
, to the generic parameter of the Enqueue
method. How does Hangfire know which concrete class, that implements the IEmailSender
interface, to actually go ahead and create, to actually perform the work?