[英]Hangfire - Multi tenant, ASP.NET Core - Resolving the correct tenant
[英]Resolving Hangfire dependencies/HttpContext in .NET Core Startup
我在.NET Core Web應用程序的Startup類中安裝並配置了Hangfire,如下所示(刪除了很多非Hangfire代碼):
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseHangfireServer();
//app.UseHangfireDashboard();
//RecurringJob.AddOrUpdate(() => DailyJob(), Cron.Daily);
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.Configure<AppSettings>(Configuration);
services.AddSingleton<IConfiguration>(Configuration);
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IPrincipal>((sp) => sp.GetService<IHttpContextAccessor>().HttpContext.User);
services.AddScoped<IScheduledTaskService, ScheduledTaskService>();
services.AddHangfire(x => x.UseSqlServerStorage(connectionString));
this.ApplicationContainer = getWebAppContainer(services);
return new AutofacServiceProvider(this.ApplicationContainer);
}
}
public interface IScheduledTaskService
{
void OverduePlasmidOrdersTask();
}
public class ScheduledTaskService : IScheduledTaskService
{
public void DailyJob()
{
var container = getJobContainer();
using (var scope = container.BeginLifetimeScope())
{
IScheduledTaskManager scheduledTaskManager = scope.Resolve<IScheduledTaskManager>();
scheduledTaskManager.ProcessDailyJob();
}
}
private IContainer getJobContainer()
{
var builder = new ContainerBuilder();
builder.RegisterModule(new BusinessBindingsModule());
builder.RegisterModule(new DataAccessBindingsModule());
return builder.Build();
}
}
如您所見,我正在使用Autofac進行DI。 每次Hangfire作業執行時,我都會設置注入新容器。
目前,我有UseHangfireDashboard()
以及添加我的定期作業注釋的調用,我在引用IPrincipal
的行上收到以下錯誤:
System.NullReferenceException:'對象引用未設置為對象的實例。'
我知道Hangfire沒有HttpContext
。 我不確定為什么它甚至會為Hangfire線程啟動那行代碼。 我最終需要為我的IPrincipal依賴解析服務帳戶。
如何解決Hangfire和HttpContext的問題?
我現在遇到的主要問題是當我添加UseHangfireServer時,我還需要解析HttpContext
在此處找到使用IoC容器
HttpContext
不可用在實例化目標類型期間,請求信息不可用。 如果在請求范圍中注冊依賴項(
InRequestScope
中的InstancePerHttpRequest
,Ninject中的InRequestScope等),則在作業激活過程中將拋出異常。因此, 整個依賴圖應該是可用的 。 如果您的IoC容器不支持多個作用域的依賴項注冊,則可以在不使用請求作用域的情況下注冊其他服務,也可以使用單獨的容器實例。
解決.net核心中的作用域依賴性需要一個在注冊和激活作業時啟動期間不可用的請求。 因此,請確保在啟動期間激活所需的服務未使用作用域生存期進行注冊。
services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();
現在剩下的就是配置應用程序以將該服務與定期作業一起使用,
public class Startup {
public IContainer ApplicationContainer { get; private set; }
public Startup(IHostingEnvironment env) {
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void Configuration(IApplicationBuilder app) {
// app.AddLogger...
//add hangfire features
app.UseHangfireServer();
app.UseHangfireDashboard();
//Add the recurring job
RecurringJob.AddOrUpdate<IScheduledTaskManager>(task => task.ProcessDailyJob(), Cron.Daily);
//app.UseMvc...
//...other code
}
public IServiceProvider ConfigureServices(IServiceCollection services) {
// Adding custom services
services.AddTransient<IScheduledTaskManager, ScheduledTaskManageImplementation>();
//add other dependencies...
// add hangfire services
services.AddHangfire(x => x.UseSqlServerStorage("<connection string>"));
//configure Autofac
this.ApplicationContainer = getWebAppContainer(services);
//get service provider
return new AutofacServiceProvider(this.ApplicationContainer);
}
IContainer getWebAppContainer(IServiceCollection service) {
var builder = new ContainerBuilder();
builder.RegisterModule(new BusinessBindingsModule());
builder.RegisterModule(new DataAccessBindingsModule());
builder.Populate(services);
return builder.Build();
}
//...other code
}
參考
為什么Hangfire嘗試解析.NET Core Startup類?
Hangfire不會在數據庫中存儲lambda表達式,它會存儲被調用的類型和方法。 然后,當計划任務運行時,它將從容器中解析該類型並調用該方法。
在您的情況下,該方法是在Startup
。
如果需要,您可以使用Autofac注冊Startup
,但最簡單的方法是擁有一個計划任務服務:
AddOrUpdate<IScheduledTaskService>(x => x.DailyTask(), Cron.Daily);
我不確定作業管理員的類型,但您可以使用作用域解決容器中的依賴關系。 您需要從using語句中的范圍解析以防止內存泄漏。 請參閱Autofac文檔
// not sure what type "jobManager" is
TYPE jobManager;
using(var scope = ApplicationContainer.BeginLifetimeScope())
{
jobManager = scope.Resolve<TYPE>();
}
RecurringJob.AddOrUpdate( ... );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.