0

我正在尝试将嵌入在 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>();

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

然而,简化注射剂的实验表明这是正常的,并且注射的物品在返回的容器的注册中仍然可见。

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

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

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

两种方式都注册它会导致双方都找到 ProcessManager,并出现一个新问题:无法解决依赖关系。然而,这只是同一问题的一个新案例。

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

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

4

1 回答 1

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从它的接口解析。

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

于 2021-03-31T00:05:17.110 回答