首页 文章

解决.NET Core Startup中的Hangfire依赖关系/ HttpContext问题

提问于
浏览
9

我在.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();
    }
}

如您所见,我正在使用Autofac进行DI . 每次Hangfire作业执行时,我都会设置注入新容器 .

目前,我有 UseHangfireDashboard() 以及添加我的定期作业注释的调用,我在引用 IPrincipal 的行上收到以下错误:

System.NullReferenceException:'对象引用未设置为对象的实例 . '

我知道Hangfire没有 HttpContext . 我'm not really sure why it'甚至为Hangfire线程发射了这行代码 . 我最终需要为我的IPrincipal依赖解析服务帐户 .

如何解决Hangfire和HttpContext的问题?

3 回答

  • 0

    为什么Hangfire尝试解析.NET Core Startup类?

    Hangfire不会在数据库中存储lambda表达式,它会存储被调用的类型和方法 . 然后,当计划任务运行时,它将从容器中解析该类型并调用该方法 .

    在您的情况下,该方法是在 Startup .

    如果需要,您可以使用Autofac注册 Startup ,但最简单的方法是拥有计划任务服务:

    AddOrUpdate<IScheduledTaskService>(x => x.DailyTask(), Cron.Daily);
    
  • 1

    我现在遇到的主要问题是当我添加UseHangfireServer时,我还需要解析HttpContext

    在这里找到Using IoC containers

    HttpContext不可用在实例化目标类型期间,请求信息不可用 . 如果在请求范围中注册依赖项(Autofac中的InstancePerHttpRequest,Ninject中的InRequestScope等),则在作业激活过程中将抛出异常 . 因此,整个依赖图应该是可用的 . 如果您的IoC容器不支持多个作用域的依赖项注册,则可以在不使用请求作用域的情况下注册其他服务,也可以使用单独的容器实例 .

    解决.net核心中的作用域依赖性需要一个在注册和激活作业时启动期间不可用的请求 . 因此,请确保在启动期间激活所需的服务未使用作用域生存期进行注册 .

    services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();
    

    现在剩下的就是配置应用程序以将该服务与定期作业一起使用,

    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
    }
    

    参考

    Hangfire 1.6.0

    Integrate HangFire With ASP.NET Core

    Using IoC containers

  • 2

    我希望从using语句中的作用域解析以防止内存泄漏 . 见Autofac Docs

    // not sure what type "jobManager" is
    TYPE jobManager;
    
    using(var scope = ApplicationContainer.BeginLifetimeScope())
    {
        jobManager = scope.Resolve<TYPE>();
    }
    
    RecurringJob.AddOrUpdate( ... );
    

相关问题