Как мне внедрить IHttpClientFactory в мое приложение Azure Service Fabric?

#c# #autofac #azure-service-fabric #asp.net-core-2.2

#c# #autofac #azure-service-fabric #asp.net-core-2.2

Вопрос:

Я пытаюсь использовать IHttpClientFactory в своем решении вместо просто экземпляров HttpClient .

startup.cs:

 services.AddHttpClient("Test", client =>
{
    client.BaseAddress = new Uri("http://localhost:57863");
    client.Timeout = new TimeSpan(0, 0, 30);
    client.DefaultRequestHeaders.Clear();
});
  

и в мои сервисы, нуждающиеся в HttpClient:

 private readonly Uri _clusterLinuxUri;
private readonly IHttpClientFactory _clientFactory;
public LiasseService(ConfigSettings settings, IHttpClientFactory clientFactory)
{
    _clusterLinuxUri = new Uri($"{settings.LinuxClusterEndpoint}");
    _clientFactory = clientFactory;
}
public async Task<LiasseDetails> CreateLiasseAsync(LiasseCreate liasseData)
{
    using (var response = await _clientFactory.CreateClient("Test")
        .PostAsJsonAsync($"{_clusterLinuxUri}{_createPath}", liasseData))
    {
        await response.CheckHttpError($"{nameof(CreateLiasseAsync)} - error in CL");
        var detailsList = await response.Content.ReadAsAsync<LiasseDetailsList>();
        return detailsList.Details.FirstOrDefault();
    }
}
  

Часть, с которой я не разобрался, заключается в том, как внедрить ее в Autofac.

program.cs

     private static void Main()
    {
        try
        {
            var builder = new ContainerBuilder();
            builder.RegisterModule(new GlobalAutofacModule());
            builder.RegisterServiceFabricSupport();
            builder.RegisterStatelessService<FacadeCore>("xxx.FacadeCoreType");

            using (builder.Build())
            {
                ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(FacadeCore).Name);
                Thread.Sleep(Timeout.Infinite);
            }
        }
        catch (Exception e)
        {
            ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
            throw;
        }
    }


    public class GlobalAutofacModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<ConfigSettings>();

            builder.RegisterType<PaymentService>().As<IPaymentService>();
            builder.RegisterType<MailerService>().As<IMailerService>();
            builder.RegisterType<LiasseService>().As<ILiasseService>();
            builder.RegisterType<AnalyseFinanciereService>().As<IAnalyseFinanciereService>();
            builder.RegisterType<ApimService>().As<IApimService>();

            builder.RegisterType<UserRepository>().As<IUserRepository>();
            builder.RegisterType<ApplicationProcessRepository>().As<IApplicationProcessRepository>();
            builder.RegisterType<LiasseRepository>().As<ILiasseRepository>();

            builder.RegisterType<CustomUserIdProvider>().As<IUserIdProvider>();
        }
    }
  

Должен ли я создать какой-либо пользовательский клиент, который реализует IHttpClientFactory , чтобы иметь возможность внедрять его? Как мне это сделать? Есть примеры? Спасибо.

Ответ №1:

Пожалуйста, смотрите Документацию по интерфейсу здесь

Итак, чтобы ответить на ваш вопрос:

1) Используя IServiceCollection из вызова метода ‘ConfigureServices’ .AddHttpClient()

2) Создайте новый конструктор контейнеров Autofac и заполните его IServiceCollection указанным выше

3) Из ConfigureServices метода возвращает new AutofacServiceProvider

 public IServiceProvider ConfigureServices(IServiceCollection services)
{
   ...

   services.AddHttpClient();

   var containerBuilder = new ContainerBuilder();

   containerBuilder.Populate(services);

   var container = containerBuilder.Build();

   return new AutofacServiceProvider(container);
}
  

P.S.
Обязательно добавьте — Autofac.Extensions.Пакет nuget DependencyInjection, чтобы иметь возможность использовать AutofacServiceProvider класс.

Комментарии:

1. к сожалению, я нахожусь в контексте service fabric, containerbuilder находится в program.cs моего api, а configureservices — в моем startup.cs

2. вероятно, моя первая попытка была давным-давно и, вероятно, не сработала, поскольку я обычно сначала пробую самое простое, хотя я не помню;)

3. Насколько я понимаю, FacadeCore является сервисом без состояния или может быть сервисом с полным состоянием, в котором вы используете WebHostBuilder и регистрируете класс startup. Я предлагаю перенести логику регистрации всех видов зависимостей в класс «Startup». Все эти вещи, связанные с SF, предназначены только для запуска вашей службы, а «запуск», как бы глупо это ни звучало, предназначен для запуска (подготовки) вашего приложения 🙂

Ответ №2:

Помимо использования решения на WebHostBuilder основе, аналогичного тому, что вы получаете при создании ванильного Asp.Net Основной проект Service Fabric, вы можете в качестве альтернативы просто сделать это

 public class HttpClientModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        
        builder.Register(_ =>
            {
                var services = new ServiceCollection();
                services.AddHttpClient();
                var containerBuilder = new ContainerBuilder();
                containerBuilder.Populate(services);
                var container = containerBuilder.Build();
                return new AutofacServiceProvider(container);
            })
            .As<IServiceProvider>()
            .SingleInstance();


        builder.Register(ctx =>
        {
            var scope = ctx.Resolve<IComponentContext>();
            var provider = scope.Resolve<IServiceProvider>();
            var factory = provider.GetService<IHttpClientFactory>();
            return factory.CreateClient();
        }).As<HttpClient>();
    }
}