与 IMediatR 库一起使用时无法在类型化客户端中注入 HttpClient

Posted

技术标签:

【中文标题】与 IMediatR 库一起使用时无法在类型化客户端中注入 HttpClient【英文标题】:Cannot inject HttpClient in typed client while using with IMediatR library 【发布时间】:2019-08-08 20:55:25 【问题描述】:

根据MSDN 中的 ASP.NET Core 2.2 文档提供的示例,可以通过在 Startup.cs 中添加以下行来将 HttpClient 注入到类型化客户端(服务类):

// Startup.cs
services.AddHttpClient<GitHubService>();

从控制器类看起来像(从现在开始我将使用 GitHub 作为域模型的简化):

// GitHubController.cs
public class GitHubController : Controller

    private readonly GitHubService _service;
    public GitHubController(GitHubService service)
    
        _service = service;
    

但是,我在我的项目中使用MediatR 库,所以我的项目结构看起来有点不同。我有 2 个项目 - GitHubFun.Api、GitHubFun.Core - 分别是 ASP.NET Core 2.2 API 项目和 .NET Core 2.2 类库。

我的控制器:

// GitHubController.cs
public class GitHubController : Controller

    private readonly IMediator _mediator;
    public GitHubController(IMediator mediator)
    
        _mediator= mediator;
    

    public async Task<IActionResult> GetGitHubRepositoryInfo(
        GetGitHubRepositoryCommand command)
    
         _mediator.Send(command);
    

还有我的处理程序类:

// GetGitHubRepositoryHandler.cs
public class GetGitHubRepositoryHandler : 
    IRequestHandler<GetGitHubRepositoryCommand , GetGitHubRepositoryCommandResult>

    private HttpClient _httpClient;

    public GetGitHubRepositoryHandler(HttpClient httpClient)
    
        _httpClient = httpClient;
    

当我发出 HTTP 请求并调用 API 方法时,它成功注入 IMediator,但在 _mediator.Send(command) 行抛出异常。

异常体:

System.InvalidOperationException:为 MediatR.IRequestHandler`2[IDocs.CryptoServer.Core.Commands.ExtractX509Command,IDocs.CryptoServer.Core.Commands.ExtractX509CommandResult] 类型的请求构造处理程序时出错。向容器注册您的处理程序。有关示例,请参阅 GitHub 中的示例。 ---> System.InvalidOperationException:尝试激活“IDocs.CryptoServer.Core.Handlers.ExtractX509CommandHandler”时无法解析“System.Net.Http.HttpClient”类型的服务

(ExtractX509CommandHandler - 只是一个真正的领域模型,而不是 GetGitHubRepositoryHandler)。

似乎 ASP.NET Core DI 无法解析 DI 并将 HttpClient 注入处理程序。

我的 Startup.cs 有以下几行:

services.AddHttpClient<ExtractX509CommandHandler>();
services.AddMediatR(
       typeof(Startup).Assembly, 
       typeof(ExtractX509CommandHandler).Assembly);

【问题讨论】:

听起来它希望您注册处理程序本身(即GetGitHubRepositoryHandler)。你做到了吗? 或者实际上,这可能是ExtractX509CommandHander 的问题。这是否将HttpClient 作为依赖项?如果是这样,您是否为此注册了类型化客户端? @ChrisPratt,是的,我已经将 HttpClient 注册为依赖项。而services.AddMediatR( typeof(Startup).Assembly, typeof(ExtractX509CommandHandler).Assembly) 也封装了ExtractX509CommandHandler的注册。 没有。你误会了。如果ExtractX509CommandHandlerHttpClient 作为依赖,那么你也需要services.AddHttpClient&lt;ExtractX509CommandHandler&gt;() @ChrisPratt,是的,我已经添加了 services.AddHttpClient()。我的问题中的 services.AddHttpClient() 行只是我为便于理解而制作的这个类的简化。 【参考方案1】:

我找到了解决方案。由于某些原因,在这种情况下,我们需要将 IHttpClientFactory 从 Microsoft.Extensions.Http.dll 而不是 HttpClient 传递给处理程序类。我只改了一行,是:

public GetGitHubRepositoryHandler(HttpClient httpClient)

现在:

public GetGitHubRepositoryHandler(IHttpClientFactory httpClientFactory)

现在它可以正常工作了。我不知道它为什么起作用,所以如果有人可以解释将 IHttpClientFactory 和 HttpClient 注入类有什么区别,那将是完美的。

【讨论】:

你找到原因了吗?有什么区别? AddHttpClient 同时注册你的服务T。在这种情况下,AddMediatR 也会这样做,所以现在您会混淆注册。【参考方案2】:

我找到了解决办法。

我使用的是 ASP.NET Core 3.1。

我的处理程序类:

public class GetProductsListQueryHandler : IRequestHandler<GetProductsListQueryModel, IEnumerable<Product>>

    private readonly HttpClient _httpClient;

    public GetProductsListQueryHandler(HttpClient httpClient)
    
        _httpClient = httpClient;
    

你需要像这样在你的 Startup 中实现你的 HttpClient :

services.AddHttpClient<IRequestHandler<GetProductsListQueryModel,IEnumerable<Product>>, GetProductsListQueryHandler>();

而且它有效! ;)

【讨论】:

以上是关于与 IMediatR 库一起使用时无法在类型化客户端中注入 HttpClient的主要内容,如果未能解决你的问题,请参考以下文章

将代理与适用于 Java 的 Google HTTP 客户端库一起使用

更新到 Swift 3.0:上下文类型“AnyObject”不能与字典文字一起使用

将 --isolatedModules 与 TS 3.2.2 一起使用时无法重新导出类型

Android webview 帖子无法与额外标题一起使用

无法让 CORS 与内容类型一起使用 - Django Rest Framework

html5视频无法与android webview一起使用