Mediatr范围问题

20

我正在使用 Mediatr 处理队列中的消息。我可以让一个简单的示例工作。但是,当我尝试将对象注入到我的处理程序中时,遇到了问题。

public class MessageCommandHandler : IRequestHandler<MessageCommand, bool>
{
    private IMyDependency myDependency;
    public MessageCommandHandler(IMyDependency myDependency)
    {
        this.myDependency = myDependency;
    }
    
    public Task<bool> Handle(MessageCommand request, CancellationToken cancellationToken)
    {
        return Task.FromResult(true);
    }
}

只有当我将IMyDependency注册为短暂作用域时,它才起作用,但是当我将它注册为作用域生命周期时,它会失败并出现错误。

Cannot resolve 'MediatR.IRequestHandler`2[MyNamespace.MessageCommand,System.Boolean]' from root provider because it requires scoped service 'MyNamespace.IMyDependency'

我需要能够注入具有作用域生命周期的依赖项。 有人有解决方案吗。

我正在使用.NET Core依赖注入框架。 它的设置如下:

services.AddHostedService<QueueConsumer>();
services.AddScoped<IMyDependency, MyDependency>();
services.AddMediatR(new Assembly[] { Assembly.GetExecutingAssembly() });

有任何想法吗?

1个回答

30
任何时候使用具有 Scoped 生命周期的依赖项,您都需要在预先创建的作用域内使用它。在 MVC 的情况下,这将在后台自动发生,但如果您直接从自己的代码中使用(例如通过控制台应用程序),则需要自己创建范围。
可以通过注入 IServiceScopeFactory 实例来实现这一点,然后使用此工厂创建一个作用域,然后从该作用域检索依赖项,例如:
public class MessageCommandHandler : IRequestHandler<MessageCommand, bool>
    {
        private IServiceScopeFactory _serviceScopeFactory;

        public MessageCommandHandler(IServiceScopeFactory serviceScopeFactory) 

        {
            _serviceScopeFactory = serviceScopeFactory;
        }

        public Task<bool> Handle(MessageCommand request, CancellationToken cancellationToken)
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var scopedServices = scope.ServiceProvider;
                var myDependency = scopedServices.GetRequiredService<IMyDependency>();
                return Task.FromResult(true);
            }
        }
    }

但是请注意(并请注意上面的代码未经测试),在我的系统中,我几乎总是会在发送中介者请求的任何内容周围创建范围,在这种情况下,任何作用域依赖项仍将自动注入到该范围中,例如。

... // some other calling class / Main method etc..

using (var scope = _serviceScopeFactory.CreateScope())
    var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
    mediator.Send(new MessageCommand());
}

_serviceScopeFactory 应该是 readonly。不过回答很好。 - Eric J.
将mediatR包装在作用域中非常有效。谢谢。 - Eternal21

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接