【问题标题】:How to configure hangfire with unity?如何统一配置hangfire?
【发布时间】:2017-07-17 23:55:36
【问题描述】:

我有 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 的每个依赖项。

统一注册

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 之前设置它。

【问题讨论】:

    标签: hangfire hangfire-unity


    【解决方案1】:

    我认为存在一个问题,您希望在 Unity 生态系统之外启动 Hangfire,但又希望 Unity 了解如何使用相关实现实例化适当的 Hangfire 接口。由于 Hangfire 本身不使用 Unity,因此您需要使用适当的配置(例如 SQL Server 连接字符串)启动 Hangfire,然后使用该配置通知 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 如何运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-01
      相关资源
      最近更新 更多