4

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

因此,根据文档,我正在使用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>();
    }

}

欧文启动

    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 的正确方法吗?

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

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

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

4

1 回答 1

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 的配置;注意这段代码是如何使用静态JobStorageHangfire 对象来实例化对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 如何运行。

于 2017-10-18T13:59:19.090 回答