我有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之前设置它。
答案 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如何操作。