Как зарегистрировать набранный сервис httpClient с помощью autofac? - PullRequest
1 голос
/ 10 ноября 2019

Я создаю веб-приложение MVC, которое вызывает API, используя .net core 2.2, используя отдельные HttpClient s для вызова каждого контроллера (того же API).

Пример:

  • Для действий контроллера пользователя: UserService (httpclient)
  • Для действий контроллера поста: PostService (httpclient)

In startup.cs Я использую DI как:

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();
    }
}

Но при вызове обработчика команд я получаю эту ошибку:

Ни один из конструкторов не найден с 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder 'on type' xxx.Application.Services.Users.UserService 'может быть вызван с доступными службами и параметрами: Невозможно разрешить параметр' System.Net.Http.HttpClient httpClient 'конструктора' Void .ctor (System.Net.Http.HttpClient, xxx.Application.Configurations.IApplicationConfigurations, Microsoft.Extensions.Logging.ILogger`1 [xxx.Application.Services.Users.UserService]) '.

Но яЗарегистрировались услуги вМодуль utofac:

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 конструктор класса:

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

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

У меня есть два вопроса:

  1. Что означает вышеуказанная ошибка?
  2. Является ли хорошей практикой использование отдельных httpclients для разных контроллеров в API?

1 Ответ

1 голос
/ 13 ноября 2019

Делая

services.AddHttpClient<IUserService, UserService>();  

Вы настроите встроенное внедрение зависимостей ядра .net для внедрения HttpClient в UserService при запросе IUserService.

Затем вы делаете

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

, который стирает встроенную конфигурацию внедрения зависимостей для IUserService. IUserService теперь зарегистрирован с UserService без учета HttpClient.

Самый простой способ добавить HttpClient - это зарегистрировать его следующим образом:

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

или

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

Если вы хотите настроить httpclient дляДля конкретного сервиса вы можете создать модуль автозапуска, который добавляет такие параметры:

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");
}));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...