如何配置统一的hangfire?

时间:2017-07-17 23:55:36

标签: hangfire hangfire-unity

我有ASP.NET Web API应用程序。该应用程序使用Unity作为IoC容器。该应用程序也使用Hangfire,我正在尝试配置Hangfire以使用Unity。

所以基于documentation我正在使用Hangfire.Unity将单位容器注册为Hangfire中的当前工作激活器。

我有一个依赖IBackgroundJobClient

的班级
 public class MyService
 {
   private MyDBContext _dbContext = null;
   private IBackgroundJobClient _backgroundJobClient = null;

   public MyService(MyDbContext dbContext, IBackgroundJobClient backgroundJobClient)
   {
     _dbContext = dbContext;
     _backgroundJobClient = backgroundJobClient;
   }
}

然而,即使在配置Hangfire.Unity之后,它也无法创建&传递BackgroundJobClient

的实例

所以我必须使用统一容器注册BackgroundJobClient的每个依赖项。

Unity注册

public class UnityConfig
{

    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });


    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }

    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<MyDbContext>(new HierarchicalLifetimeManager(), new InjectionFactory(x => new MyDbContext()));       

        // register hangfire dependencies
        container.RegisterType<IBackgroundJobClient, BackgroundJobClient>();
        container.RegisterType<JobStorage, SqlServerStorage>(new InjectionConstructor("HangfireConnectionString"));
        container.RegisterType<IJobFilterProvider, JobFilterAttributeFilterProvider>(new InjectionConstructor(true));
        container.RegisterType<IBackgroundJobFactory, BackgroundJobFactory>();
        container.RegisterType<IRecurringJobManager, RecurringJobManager>();
        container.RegisterType<IBackgroundJobStateChanger, BackgroundJobStateChanger>();
    }

}

OWIN初创公司

    public class Startup
    {        
        public void Configuration(IAppBuilder app)
        {
            var container = UnityConfig.GetConfiguredContainer();


            Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage("HangfireConnectionString");
            Hangfire.GlobalConfiguration.Configuration.UseUnityActivator(container);

            // if i dont call UseSqlServerStorage() above then UseHangfireDashboard() method fails with exception
            //JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API.

            app.UseHangfireDashboard();
            app.UseHangfireServer();                      

            RecurringJob.AddOrUpdate<MyService>(x => x.Prepare(), Cron.MinuteInterval(10));
        }
    }

代码正在使用此类配置。不过我有疑问:

这是使用Hangfire配置Unity的正确方法吗?

为什么我需要在OWIN启动时调用Hangfire.GlobalConfiguration.Configuration.UseSqlServerStorage("HangfireConnectionString"),即使SqlServerStorage已经在Unity容器中注册为JobStorage

如果我不在OWIN启动时调用UseSqlServerStorage()方法,那么我会在app.UseHangfireDashboard()方法上获得异常。

  

JobStorage.Current属性值尚未初始化。你必须   在使用Hangfire客户端或服务器API之前设置它。

1 个答案:

答案 0 :(得分:1)

我认为您希望在Unity生态系统之外启动Hangfire,但也希望Unity了解如何使用相关实现实例化相应的Hangfire接口。由于Hangfire本身不使用Unity,因此您需要使用适当的配置启动Hangfire,例如SQL Server连接字符串,然后使用该配置通知Unity如何实例化Hangfire接口。我能够通过为SQL设置全局Hangfire配置来解决此问题,然后使用相同的Hangfire静态实例来设置Unity。

以下是示例代码,首先您将看到如何使用连接字符串启动hangfire控制面板和服务器:

public void Configuration(IAppBuilder app)
{ 
    var configuration = new Configuration(); // whatever this is for you

    GlobalConfiguration.Configuration.UseSqlServerStorage(
        configuration.GetConnectionString());

    GlobalConfiguration.Configuration.UseActivator(
        new HangfireContainerActivator(UnityConfig.GetConfiguredContainer()));

    app.UseHangfireDashboard("/hangfire", new DashboardOptions
    {
        Authorization = new[] {new HangfireAuthorizationFilter()}
    }); 
    app.UseHangfireServer();
}

作为第二个例子,这是Unity for Hangfire的配置;注意此代码如何使用静态JobStorage Hangfire对象来实例化JobStorage的任何请求。

    public static void RegisterHangfire(IUnityContainer container)
    {
        container.RegisterType<JobStorage>(new InjectionFactory(c => JobStorage.Current));
        container.RegisterType<IJobFilterProvider, JobFilterAttributeFilterProvider>(new InjectionConstructor(true));
        container.RegisterType<IBackgroundJobFactory, BackgroundJobFactory>();
        container.RegisterType<IRecurringJobManager, RecurringJobManager>();
        container.RegisterType<IBackgroundJobClient, BackgroundJobClient>();
        container.RegisterType<IBackgroundJobStateChanger, BackgroundJobStateChanger>();
    }

我相信这种方法可以为您提供最好的两个世界,在这两个世界中,您只需设置一次SQL Server连接并尽早启动它,然后启动Hangfire,然后使用该实例告诉Unity如何操作。