c# - 如何使用 autofac 注册类型化的 httpClient 服务?

标签 c# dependency-injection .net-core httpclient autofac

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

前任:

  • 对于用户 Controller 操作:UserService (httpclient)
  • 对于后期 Controller 操作: PostService (httpclient)

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

    但是当调用命令处理程序时,我得到了这个错误:

    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 模块中注册了服务:
    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}";
    }
    

    我有两个问题:
  • 上面的错误是什么意思?
  • 为 api 中的不同 Controller 使用单独的 httpclients 是一种好习惯吗?
  • 最佳答案

    通过做

    services.AddHttpClient<IUserService, UserService>();  
    

    您将配置 native .net 核心依赖注入(inject)以注入(inject) HttpClientUserService当一个 IUserService被要求。

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

    这将删除 IUserService 的 native 依赖注入(inject)配置. 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,您可以创建一个 autofac 模块,该模块添加如下参数:
    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");
    }));
    

    关于c# - 如何使用 autofac 注册类型化的 httpClient 服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58791239/

    相关文章:

    java - 具有动态参数的 Spring-Boot @Bean 生产者

    iis - 将 asp.net core 配置排除在源代码和管道之外

    windows - 如何使用 launch.json 定位平台

    .net-core - 将 ASP.NET Core Razor 页面中的默认页面更改为登录页面

    c# - 如何选择字符串字段以特定字符串开头的所有行

    c# - 查找每小时创建的最大行数?

    javascript - AngularJS 种子 : putting JavaScript into separate files (app. js、controllers.js、directives.js、filters.js、services.js)

    java - Dagger 2 - 使用 @Named 注入(inject)多个相同类型的对象不起作用

    c# - Serilog 不适用于 Reliable Actor Services

    c# - 如何让两个应用程序通过 LAN 找到并连接?