如何在 dotnet 核心控制台应用程序中使用 Autofac 配置 Hangfire

时间:2021-03-27 01:24:15

标签: .net-core console-application autofac hangfire-autofac

我正在尝试将嵌入在 Kestrel 网络服务器中的有效 Hangfire 设置移植到控制台应用程序。我已经修改了网络应用,所以它仍然提供 Hangfire 仪表板,但不启动自己的 Hangfire 服务器。

我必须移植的代码使用 Autofac。我已将 Hangfire.Autofac 包添加到控制台应用程序中,并且已经执行了对 Hangfire Autofac .net core 3.1

的回答中详述的所有步骤

当我创建作业(使用 Web 应用)时,控制台应用 Hangfire 服务器尝试执行该作业,但我收到此失败消息:

The requested service 'AED.ServicesLayer.JobProcessing.ProcessManager' has not been registered.

为此,我们检查了控制台应用程序中 Autofac 的设置。这就是我设置容器的方式。

IConfiguration config = new ConfigurationBuilder()
  .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  .Build();
var containerBuilder = new Autofac.ContainerBuilder();
containerBuilder.RegisterInstance(Log.Logger).AsImplementedInterfaces();
containerBuilder.RegisterModule(new RepositoryModule(config));
containerBuilder.RegisterType<UserService>().As<IUserService>();
containerBuilder.RegisterInstance(config).As<IConfiguration>();
containerBuilder.RegisterModule(new JobProcessingModule(config));
var container = containerBuilder.Build();

当应用程序执行时,在 JobProcessingModule 中遇到断点证明以下代码行被执行。

builder.RegisterType<ProcessManager>().As<IProcessManager>();

非常奇怪的是,传递给 JobProcessingModule.Load(containerBuilder) 的 containerBuilder 实例与调用 RegisterModule 的 containerBuilder 对象不同。

但是,使用简化的可注入项的实验表明这是正常的,并且注入的项在返回的容器的注册中仍然可见。

重新检查记录的失败,我们注意到该类是由类名而不是由接口提及的。通过删除接口注册来改变注册,像这样

builder.RegisterType<ProcessManager>();//.As<IProcessManager>();

导致在 Hangfire 控制台主机中找到 ProcessManager,但在创建作业时导致 Web 应用程序中的运行时错误。

以两种方式注册它导致ProcessManager被两者找到,新问题浮出水面:无法解决依赖关系。然而,这只是同一问题的一个新案例。

虽然这让我可以继续让控制台主机工作,但我不喜欢我不理解的代码。 为什么控制台主机需要通过类名注册,而 Web 应用不需要?

导致这种情况的原因也导致 Hangfire.IBackgroundJobClient 无法解析到后台作业客户端。这是一个hangfire类,所以看起来确实存在一个根本问题。

1 个答案:

答案 0 :(得分:0)

经过长时间的调查,最终通过实验证实了这段代码

_recurringJobManager.AddOrUpdate(
  insertResult.ToString(), 
  pm => pm.RunScheduledJobs(insertResult), interval.CrontabExpression
);

对问题中描述的行为负责。 AddOrUpdate 是通用方法。当它没有显式类型化时,它从传递给它的对象的中获取它的类型。当方法显式类型为接口时,像这样

_recurringJobManager.AddOrUpdate<IProcessManager>(
  insertResult.ToString(), 
  pm => pm.RunScheduledJobs(insertResult), interval.CrontabExpression
);

它仍然与对象兼容,但 Hangfire 获取的类型是接口,控制台应用程序可以从其接口解析 ProcessManager

为什么在 Web 托管的 Hangfire 服务器中没有出现问题仍然是一个谜,但至少现在我对在我没有的情况下没有问题感到困惑。