如何使用 autofac 注册类型化的 httpClient 服务? [英] How to register typed httpClient service with autofac?

查看:76
本文介绍了如何使用 autofac 注册类型化的 httpClient 服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建 MVC Web 应用程序,它使用 .net core 2.2 调用 api,使用单独的 HttpClient 来调用每个控制器(相同的 api).

I'm creating MVC web application which calls an api using .net core 2.2 using separate HttpClients to call each controller (same api).

例如:

  • 对于用户控制器操作:UserService (httpclient)
  • 对于后控制器操作:PostService (httpclient)

startup.cs 中,我将 DI 用作:

In startup.cs I use DI as:

services.AddHttpClient<IUserService, UserService>();
services.AddHttpClient<IPostService, PostService>();

在我的处理程序中:

public class CommandHandler : IRequestHandler<Command, BaseResponse>
{
    private readonly IUserService _userService;

    public CommandHandler(IUserService userService)
    {
        _userService = userService;
    }

    public Task<BaseResponse> Handle(Command request, CancellationToken cancellationToken)
    {
        throw new System.NotImplementedException();
    }
}

但是在调用命令处理程序时出现此错误:

But when invoking command handler I get this error:

未找到任何构造函数'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' 类型'xxx.Application.Services.Users.UserService' 可以用可用的服务和参数:无法解析参数构造函数Void"的System.Net.Http.HttpClient httpClient".ctor(System.Net.Http.HttpClient,xxx.Application.Configurations.IApplicationConfigurations,Microsoft.Extensions.Logging.ILogger`1[xxx.Application.Services.Users.UserService])'.

None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'xxx.Application.Services.Users.UserService' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Net.Http.HttpClient httpClient' of constructor 'Void .ctor(System.Net.Http.HttpClient, xxx.Application.Configurations.IApplicationConfigurations, Microsoft.Extensions.Logging.ILogger`1[xxx.Application.Services.Users.UserService])'.

但是我已经在 autofac 模块中注册了服务:

But I've registered services in autofac module:

public class ServiceModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterAssemblyTypes(typeof(ServiceModule).Assembly)
                .Where(t => t.Namespace.StartsWith("xxx.Application.Services"))
                .AsImplementedInterfaces().InstancePerLifetimeScope();
    }
}

这是我的 UserService 类构造函数:

Here is my UserService class constructor:

public UserService (HttpClient httpClient, IApplicationConfigurations applicationConfig, ILogger<UserService> logger)
{
    _httpClient = httpClient;
    _applicationConfig = applicationConfig;
    _logger = logger;

    _remoteServiceBaseUrl = $"{_applicationConfig.WebApiBaseUrl}";
}

我有两个问题:

  1. 上述错误是什么意思?
  2. 在 api 中为不同的控制器使用单独的 httpclients 是一种好的做法吗?

推荐答案

通过做

services.AddHttpClient<IUserService, UserService>();  

您将配置原生 .net 核心依赖项注入,以便在请求 IUserService 时将 HttpClient 注入到 UserService.

You will configure the native .net core dependency injection to inject HttpClient to UserService when a IUserService is requested.

然后你做

builder.RegisterAssemblyTypes(typeof(ServiceModule).Assembly)
       .Where(t => t.Namespace.StartsWith("xxx.Application.Services"))
       .AsImplementedInterfaces().InstancePerLifetimeScope();

这将清除 IUserService 的本机依赖项注入配置.IUserService 现在注册到 UserService 没有任何 HttpClient.

which will erase the native dependency injection configuration for IUserService. The IUserService is now registered with UserService without any HttpClient in mind.

添加 HttpClient 的最简单方法是像这样注册它:

The simplest way to add HttpClient would be to register it like this :

builder.Register(c => new HttpClient())
       .As<HttpClient>();

services.AddHttpClient(); // register the .net core IHttpClientFactory 
builder.Register(c => c.Resolve<IHttpClientFactory>().CreateClient())
       .As<HttpClient>(); 

如果您想为特定服务配置 httpclient,您可以创建一个 autofac 模块,添加如下参数:

If you want to configure your httpclient for a specific service you can create an autofac module which add parameters like this :

public class HttpClientModule<TService> : Module
{
    public HttpClientModule(Action<HttpClient> clientConfigurator)
    {
        this._clientConfigurator = clientConfigurator;
    }

    private readonly Action<HttpClient> _clientConfigurator;

    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        base.AttachToComponentRegistration(componentRegistry, registration);

        if (registration.Activator.LimitType == typeof(TService))
        {
            registration.Preparing += (sender, e) =>
            {
                e.Parameters = e.Parameters.Union(
                  new[]
                  {
                    new ResolvedParameter(
                        (p, i) => p.ParameterType == typeof(HttpClient),
                        (p, i) => {
                            HttpClient client = i.Resolve<IHttpClientFactory>().CreateClient();
                            this._clientConfigurator(client);
                            return client;
                        }
                    )
                  });
            };
        }
    }
}

然后

builder.RegisterModule(new HttpClientModule<UserService>(client =>
{
    client.BaseAddress = new Uri("https://api.XXX.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.XXX.v3+json");
    client.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-XXX");
}));

这篇关于如何使用 autofac 注册类型化的 httpClient 服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆