代码之家  ›  专栏  ›  技术社区  ›  Nanou Ponette

HangFire with Castle Windsor在后台作业中使用依赖项

  •  1
  • Nanou Ponette  · 技术社区  · 7 年前

    我需要一种方法来运行后台作业,并了解HangFire。我成功地安装了一切,但我似乎无法与温莎一起工作。

    问题是:

    系统无效操作异常:HttpContext。电流为空。 PerWebRequestLifestyle只能在ASP.Net中使用

    这是我的代码:

    Global.asax:

    protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
    
            // Set up IoC Container
            var container = new WindsorContainer(Server.MapPath("~/Configuration/IoC/windsor.config"));
    
            // Set up HangFire with IoC
            JobActivator.Current = new WindsorJobActivator(container.Kernel);
        }
    

        public void Configuration(IAppBuilder app)
        {    
            GlobalConfiguration.Configuration.UseSqlServerStorage("ILVO");
    
            app.UseHangfireServer();
            app.UseHangfireDashboard();
        }
    

    public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register
            (
                Component.For<ApplicationContextBuilder>().ImplementedBy<ApplicationContextBuilder>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IApplicationContextProvider>().ImplementedBy<ApplicationContextProvider>().LifeStyle.HybridPerWebRequestTransient(),
    
                Component.For<ICacheService>().ImplementedBy<CacheService>().LifestyleSingleton(),
                Component.For<ISessionProvider>().ImplementedBy<SessionProvider>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IRepository>().ImplementedBy<Repository>().LifeStyle.HybridPerWebRequestTransient(),
    
                Component.For<IEmployeeService>().ImplementedBy<EmployeeService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IGeneralService>().ImplementedBy<GeneralService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<ITaskService>().ImplementedBy<TaskService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<ISuggestionService>().ImplementedBy<SuggestionService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IAnnouncementService>().ImplementedBy<AnnouncementService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IUploadService>().ImplementedBy<UploadService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<ITaskTrackingService>().ImplementedBy<TaskTrackingService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IRequestVpnService>().ImplementedBy<RequestVpnService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IEmailService>().ImplementedBy<EmailService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IEmployeePlannerService>().ImplementedBy<EmployeePlannerService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<ISalaryToolService>().ImplementedBy<SalaryToolService>().LifeStyle.HybridPerWebRequestTransient(),
                Component.For<IAccessRightService>().ImplementedBy<AccessRightService>().LifeStyle.HybridPerWebRequestTransient()
            );
        }
    

    有什么解决办法吗?我真的很想在我的后台工作中运行数据库操作。

    感谢您的帮助!谢谢。

    我为HangFire制作了一个单独的IoC容器,只提供了我需要的服务!我还制作了一个类BackroundJobHelper,我存储了在HangFire中运行所需的所有函数。

    private WindsorContainer _hangFireContainer;
    
            // Set up IoC Container for HangFire
            _hangFireContainer = new WindsorContainer();
            _hangFireContainer.Register(
                Component.For<BackgroundJobHelper>(),
                Component.For<ICacheService>().ImplementedBy<CacheService>().LifestylePerThread(),
                Component.For<ISessionProvider>().ImplementedBy<SessionProvider>().LifestylePerThread(),
                Component.For<IRepository>().ImplementedBy<Repository>().LifestylePerThread(),
                Component.For<IEmployeePlannerService>().ImplementedBy<EmployeePlannerService>().LifestylePerThread(),
                Component.For<ISalaryToolService>().ImplementedBy<SalaryToolService>().LifestylePerThread()
            );
    
            JobActivator.Current = new WindsorJobActivator(_hangFireContainer.Kernel);
    

    BackgroundJobHelper.cs

    public class BackgroundJobHelper
    {
        private readonly IEmployeePlannerService _employeePlannerService;
        private readonly ISalaryToolService _salaryToolService;
    
        public BackgroundJobHelper()
        {
    
        }
    
        public BackgroundJobHelper(IEmployeePlannerService employeePlannerService, ISalaryToolService salaryToolService)
        {
            _employeePlannerService = employeePlannerService;
            _salaryToolService = salaryToolService;
        }
    }
    

    控制器

    在控制器中,我用我想在HangFire中运行的函数调用BackgroundJobHelper类。

    BackgroundJob.Enqueue(() => _backgroundJobHelper.Function());
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Fran    7 年前

    问题是Hangfire独立于房屋应用程序运行自己的服务器(线程)。

    您的容器运行在看起来像MVC应用程序的内部。因此,在注册时,HttpContext可用,您的服务将在PerRequest范围内注册。

    here

    here 你不能将PerRequest与Hangfire一起使用,因为你正在解决这个问题。

        2
  •  2
  •   Cubelaster    5 年前

    https://github.com/BredStik/HangFire.Windsor http://docs.hangfire.io/en/latest/background-methods/using-ioc-containers.html 基本上,你需要注册你的工作/服务和volia。 注册是通过您的DI提供商(Windsor)以通常的方式完成的。

    protected void Application_Start()
    {
        _container = new WindsorContainer();            
    
        /* Register types */
        /* _container.Register(Component.For<ISomeInterface>().ImplementedBy<SomeImplementation>()); */
    
    JobActivator.Current = new WindsorJobActivator(_container.Kernel);
    }
    

    windsorContainer.Register(Component.For<SomeJob>().ImplementedBy<SomeJob>());
    

    windsorContainer是IWindsorContainer。这是在Global.asax中完成的。 在启动过程中,您可以调用:

    RecurringJob.AddOrUpdate<SomeJob>(x => x.Run(null), Properties.Settings.Default.SomeJobCron);