0
\$\begingroup\$

I tried following IHttpContextAccessor pattern but for Hangfire context. What I'm mostly interested in is CustomScope class with Resolve method. I'm using ActivatorUtilities there because otherwise I would need to register TestJob to IServiceCollection, this way it resolves without the need to register it.

Snippet is for .NET 6

Is there a better way to do this?

using Hangfire;
var host = Host.CreateDefaultBuilder(args)
 .ConfigureServices((context, services) =>
 { 
 services.AddScoped<IUser, User>();
 services.AddScoped<IHangfireContext, HangfireContext>();
 services.AddTransient<CustomJobActivator>();
 services.AddHangfire((provider, configuration) =>
 {
 configuration.UseActivator(provider.GetService<CustomJobActivator>()!);
 configuration.UseSqlServerStorage("server=.;database=Hangfire;trusted_connection=True;");
 });
 services.AddHangfireServer();
 })
 .Build();
var background = host.Services.GetService<IBackgroundJobClient>();
background.Enqueue<TestJob>(x => x.Run());
await host.RunAsync();
public class TestJob
{
 private readonly ILogger<TestJob> _logger;
 private readonly IUser _user;
 public TestJob(ILogger<TestJob> logger, IUser user)
 {
 _logger = logger;
 _user = user;
 }
 public void Run()
 {
 _logger.LogInformation("Job run for id {job} job name {name}", _user.Id, _user.Name);
 }
}
public interface IUser
{
 public string Id { get; }
 public string Name { get; }
}
public class User : IUser
{
 public User(IHangfireContext hangfireContext)
 {
 Id = hangfireContext.JobActivatorContext?.BackgroundJob.Id ?? "-";
 Name = hangfireContext.JobActivatorContext?.BackgroundJob.Job.Type.Name ?? "-";
 }
 public string Id { get; }
 public string Name { get; }
}
public class CustomJobActivator : JobActivator
{
 private readonly IServiceProvider _serviceProvider;
 public CustomJobActivator(IServiceProvider serviceProvider)
 {
 _serviceProvider = serviceProvider;
 }
 public override object ActivateJob(Type jobType)
 {
 return _serviceProvider.GetService(jobType)!;
 }
 public override JobActivatorScope BeginScope(JobActivatorContext context)
 {
 return new CustomScope(_serviceProvider.CreateScope(), context);
 }
}
public class CustomScope : JobActivatorScope
{
 private readonly IServiceScope _serviceScope;
 public CustomScope(IServiceScope serviceScope, JobActivatorContext context)
 {
 _serviceScope = serviceScope;
 var hangfireContext = _serviceScope.ServiceProvider.GetRequiredService<IHangfireContext>();
 hangfireContext.JobActivatorContext = context;
 }
 public override object Resolve(Type type)
 {
 return ActivatorUtilities.CreateInstance(_serviceScope.ServiceProvider, type);
 }
 public override void DisposeScope()
 {
 _serviceScope.Dispose();
 }
}
public class HangfireContext : IHangfireContext
{
 public JobActivatorContext? JobActivatorContext { get; set; }
}
public interface IHangfireContext
{
 JobActivatorContext? JobActivatorContext { get; set; }
}
asked Jun 3, 2022 at 10:54
\$\endgroup\$
3
  • \$\begingroup\$ My bad, was looking for .net tags and in the end I forgot C# tag \$\endgroup\$ Commented Jun 3, 2022 at 10:58
  • \$\begingroup\$ refer this : docs.hangfire.io/en/latest/background-methods/…, Also, you could use Autofac extension, it would make things easier. \$\endgroup\$ Commented Jun 3, 2022 at 12:26
  • \$\begingroup\$ I'm trying to do it with default DI container. I mean this works, I'm just wondering if I missed something \$\endgroup\$ Commented Jun 3, 2022 at 13:08

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.