如何使用unity配置hangfire?

LP1*_*P13 5 hangfire hangfire-unity

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

因此,根据文档,我使用Hangfire.Unity它将 Unity 容器注册为 Hangfire 中的当前作业激活器。

我有一个依赖于IBackgroundJobClient

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

   public MyService(MyDbContext dbContext, IBackgroundJobClient backgroundJobClient)
   {
     _dbContext = dbContext;
     _backgroundJobClient = backgroundJobClient;
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,即使在配置之后,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>();
    }

}
Run Code Online (Sandbox Code Playgroud)

欧文初创公司

    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));
        }
    }
Run Code Online (Sandbox Code Playgroud)

代码正在使用这样的配置。不过我有疑问:

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

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

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

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

Jer*_*ali 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();
}
Run Code Online (Sandbox Code Playgroud)

作为第二个示例,这是 Hangfire 的 Unity 配置;请注意此代码如何使用静态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>();
    }
Run Code Online (Sandbox Code Playgroud)

我相信这种方法可以让您两全其美,您只需设置一次 SQL Server 连接,并尽早启动 Hangfire,然后使用该实例来告诉 Unity 如何行为。