im1*_*ike 9 .net c# autofac hangfire hangfire-autofac
我在.NET Core Web应用程序的Startup类中安装并配置了Hangfire,如下所示(删除了很多非Hangfire代码):
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseHangfireServer();
//app.UseHangfireDashboard();
//RecurringJob.AddOrUpdate(() => DailyJob(), Cron.Daily);
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<AppSettings>(Configuration);
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IPrincipal>((sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User);
services.AddScoped<IScheduledTaskService, ScheduledTaskService>();
services.AddHangfire(x => x.UseSqlServerStorage(connectionString));
this.ApplicationContainer = getWebAppContainer(services);
return new AutofacServiceProvider(this.ApplicationContainer);
}
}
public interface IScheduledTaskService
{
void OverduePlasmidOrdersTask();
}
public class ScheduledTaskService : IScheduledTaskService
{
public void DailyJob()
{
var container = getJobContainer();
using (var scope = container.BeginLifetimeScope())
{
IScheduledTaskManager scheduledTaskManager = scope.Resolve<IScheduledTaskManager>();
scheduledTaskManager.ProcessDailyJob();
}
}
private IContainer getJobContainer()
{
var builder = new ContainerBuilder();
builder.RegisterModule(new BusinessBindingsModule());
builder.RegisterModule(new DataAccessBindingsModule());
return builder.Build();
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我正在使用Autofac进行DI.每次Hangfire作业执行时,我都会设置注入新容器.
目前,我有UseHangfireDashboard()一个调用添加我的定期作业注释,我在行参考时收到以下错误IPrincipal:
System.NullReferenceException:'对象引用未设置为对象的实例.'
我知道Hangfire没有HttpContext.我不确定为什么它甚至会为Hangfire线程启动那行代码.我最终需要为我的IPrincipal依赖解析服务帐户.
如何解决Hangfire和HttpContext的问题?
我现在遇到的主要问题是当我添加 UseHangfireServer 时,我也需要解析 HttpContext
在这里找到使用 IoC 容器
HttpContext不可用请求信息在目标类型实例化期间不可用。如果您在请求范围内(
InstancePerHttpRequest在 Autofac、InRequestScopeNinject 等中)注册依赖项,则在作业激活过程中将引发异常。因此,整个依赖图应该可用。要么注册附加服务而不使用请求范围,要么使用单独的容器实例(如果您的 IoC 容器不支持多个范围的依赖项注册)。
解决 .net core 中的范围依赖关系需要一个在注册和激活作业时启动期间不可用的请求。因此,请确保启动期间激活所需的服务未使用范围生命周期进行注册。
services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();
Run Code Online (Sandbox Code Playgroud)
现在剩下的就是配置应用程序以将该服务与重复作业一起使用,
public class Startup {
public IContainer ApplicationContainer { get; private set; }
public Startup(IHostingEnvironment env) {
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void Configuration(IApplicationBuilder app) {
// app.AddLogger...
//add hangfire features
app.UseHangfireServer();
app.UseHangfireDashboard();
//Add the recurring job
RecurringJob.AddOrUpdate<IScheduledTaskManager>(task => task.ProcessDailyJob(), Cron.Daily);
//app.UseMvc...
//...other code
}
public IServiceProvider ConfigureServices(IServiceCollection services) {
// Adding custom services
services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();
//add other dependencies...
// add hangfire services
services.AddHangfire(x => x.UseSqlServerStorage("<connection string>"));
//configure Autofac
this.ApplicationContainer = getWebAppContainer(services);
//get service provider
return new AutofacServiceProvider(this.ApplicationContainer);
}
IContainer getWebAppContainer(IServiceCollection service) {
var builder = new ContainerBuilder();
builder.RegisterModule(new BusinessBindingsModule());
builder.RegisterModule(new DataAccessBindingsModule());
builder.Populate(services);
return builder.Build();
}
//...other code
}
Run Code Online (Sandbox Code Playgroud)
参考
我不确定 jobmanager 的类型,但是您可以使用作用域解决容器中的依赖关系。您需要从 using 语句中的范围进行解析,以防止内存泄漏。请参阅Autofac 文档
// not sure what type "jobManager" is
TYPE jobManager;
using(var scope = ApplicationContainer.BeginLifetimeScope())
{
jobManager = scope.Resolve<TYPE>();
}
RecurringJob.AddOrUpdate( ... );
Run Code Online (Sandbox Code Playgroud)