【问题标题】:.NET Core console app Mediatr command handler doesn't get called.NET Core 控制台应用程序 Mediatr 命令处理程序不会被调用
【发布时间】:2022-05-05 00:04:45
【问题描述】:

我遇到了未调用 Mediatr 命令处理程序的问题。 我有以下解决方案结构。

Project.sln -> Application layer (.NET standard class library) -> Jobs (.NET standard class library) -> Job Server (.NET Core console app)

这个想法是 Job Server 使用调度程序 (Quartz.NET) 来执行 Jobs。实际的业务逻辑在应用层。应用层使用使用 Mediatr 连接的 CQRS 模式。我正在使用 Microsoft 依赖注入库。

Job Server Main 方法(带 DI 代码):

public class Program
{
    static ManualResetEvent _quitEvent = new ManualResetEvent(false);

    static void Main(string[] args)
    {
        Console.WriteLine("Job Server started");

        //DI setup
        var serviceProvider = new ServiceCollection()
            .AddQuartz()
            .AddTransient<InitializeJobServer>()
            .AddTransient<ProcessAdRssFeedsJob>()
            .AddScoped<IConfigService, ConfigService>()
            .AddScoped<IRssService, RssService>()
            .AddScoped<IBaseService, BaseService>()
            .AddMediatR(typeof(ProcessAdSectionsRssCommand).GetType().Assembly)
            .AddDbContext<MyDbContext>(options =>
                options.UseNpgsql("xxx"))
            .AddMemoryCache()
            .BuildServiceProvider();

        Console.CancelKeyPress += (sender, eArgs) => {
            _quitEvent.Set();
            eArgs.Cancel = true;
        };

        Task.Run(async () =>
        {
            await serviceProvider.GetService<InitializeJobServer>().Start();
        });

        _quitEvent.WaitOne();
        Console.WriteLine("Job Server ended");
    }
}

来自 Quartz.net 工作的代码:

[DisallowConcurrentExecution]
public class ProcessAdRssFeedsJob : IJob
{
    private readonly IMediator _mediator;

    public ProcessAdRssFeedsJob(IMediator mediator)
    {
        _mediator = mediator;
    }

    public Task Execute(IJobExecutionContext context)
    {
        try
        {
            _mediator.Send(new ProcessAdSectionsRssCommand());               
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        return null;
    }
}

Mediatr 命令:

public class ProcessAdSectionsRssCommand : IRequest<bool>
{

    public class Handler : IRequestHandler<ProcessAdSectionsRssCommand, bool>
    {
        private readonly MyDbContext _context;
        private readonly IRssService _rssService;
        private readonly IConfigService _configService;

        public Handler(
            MyDbContext context,
            IRssService rssService,
            IConfigService configService)
        {
            _context = context;
            _rssService = rssService;
            _configService = configService;
        }

        public async Task<bool> Handle(ProcessAdSectionsRssCommand request, CancellationToken cancellationToken)
        {
            var config = await _configService.GetAllConfigs();

            var r0 = await _rssService.GetAdSectionRssUrls();
            // etc.
            return true;
        }
    }
}

经过调试,我得出结论,代码在初始化ProcessAdSectionsRssCommand 类后停止执行(如果我创建了一个空的构造函数,它将被执行)。不幸的是,我没有收到任何实际的错误消息,我认为可能会吞下某种异常。 Handler 类据我所知永远不会被初始化。

  • Mediatr 版本:6.0.0
  • .NET 代码 SDK 版本:2.2
  • Microsoft DI 版本(Microsoft.Extensions.DependencyInjection):2.2.0

我怀疑这是某种与 DI + Mediatr 相关的问题。有人有什么想法吗? 谢谢。

【问题讨论】:

  • IMediator.Send 返回一个Task,所以我建议在你的工作中使用async 关键字Execute 方法定义和await 调用你的Send 方法_mediator。可能是操作不再被监控,因此没有在任何地方捕获异常。
  • @MickaëlDerriey 感谢您的建议!在应用了建议的更改后,我最终得到了异常 System.InvalidOperationException: Handler was not found for request of type MediatR.IRequestHandler 2[xxx.Application.Rss.Commands.ProcessAdSectionsRss.ProcessAdSectionsRssCommand,System.Boolean]. Register your handlers with the container. See the samples in GitHub for examples. 我猜,问题仍然存在 - 如何设置依赖注入以在控制台应用程序中工作?请注意,在 ASP.NET Core 项目中,此逻辑有效。另外,我试图从处理程序中删除所有依赖项
  • 我认为这告诉我们a) MediatR 甚至看不到处理程序类,或者b) MediatR 尝试实例化处理程序时出现问题。您是否可以尝试将处理程序类移出请求类,使其不再是嵌套类?此外,在您的代码示例中,处理程序依赖于未在容器中注册的 MyDbContext。是拼写错误还是缺少注册?
  • 我试图将处理程序类移到请求类之外。 MyDbContext 是正确的名称(以前复制/粘贴问题),它已注册。我还从处理程序的 ctor 中删除了所有依赖项。我还尝试在 DI 中注册请求/处理程序类。到目前为止同样的问题。
  • 好的,我终于设法解决了这个问题。原来需要在ServiceCollection中显式注册handler。你可以在this commit 中看到我是如何做到的。 @MickaëlDerriey 感谢您的帮助!

标签: c# .net dependency-injection console mediatr


【解决方案1】:

我认为您在调用Send() 方法时缺少await

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-22
    • 2021-08-24
    相关资源
    最近更新 更多