Asp.net-Core

Mediatr 範圍問題

  • February 28, 2022

我正在使用 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() });

有任何想法嗎?

每當您使用具有 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);
           }
       }
   }

但是(請注意,上面的程式碼未經測試),在我自己的系統中,我幾乎總是圍繞發送調解器請求的任何內容創建範圍,在這種情況下,任何 Scoped 依賴項仍將在此範圍內自動注入,例如

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

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

引用自:https://stackoverflow.com/questions/57008673