You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core中泛型类依赖注入的优化实现方案咨询

优化方案说明

首先需要修正原APIClient的一个关键问题:每次创建HttpClient和HttpClientHandler会导致TCP端口耗尽,违反ASP.NET Core的HttpClient最佳实践。正确的做法是注入HttpClient(由DI容器管理生命周期)或使用IHttpClientFactory。

修正后的基础泛型客户端实现

public class APIClient<T1, T2> : IApiClient<T1, T2> 
    where T1 : class
    where T2 : class
{
    private readonly HttpClient _httpClient;

    public APIClient(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<T2> PostToEndPoint(string url, T1 input)
    {
        // 注意:方法名是PostToEndPoint,内部应使用PostAsJsonAsync而非PutAsJsonAsync
        var response = await _httpClient.PostAsJsonAsync(url, input);
        response.EnsureSuccessStatusCode(); // 建议添加,确保请求成功
        var content = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<T2>(content);
    }
}

public interface IApiClient<T1, T2> where T1 : class
                                    where T2 : class
{
    Task<T2> PostToEndPoint(string url,T1 input);
}

注册时改用AddHttpClient管理:

// 基础注册
builder.Services.AddHttpClient(typeof(IApiClient<,>), typeof(APIClient<,>));

// 如需统一配置BaseAddress等参数
builder.Services.AddHttpClient<IApiClient<,>, APIClient<,>>()
    .ConfigureHttpClient(client => 
    {
        client.BaseAddress = new Uri("https://your-api-base-url.com/");
    });

方案一:工厂模式减少注入实例数量

通过工厂类统一管理不同泛型参数的IApiClient实例获取,控制器仅需注入工厂。

工厂接口与实现

public interface IApiClientFactory
{
    IApiClient<TInput, TOutput> CreateClient<TInput, TOutput>() 
        where TInput : class 
        where TOutput : class;
}

public class ApiClientFactory : IApiClientFactory
{
    private readonly IServiceProvider _serviceProvider;

    public ApiClientFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IApiClient<TInput, TOutput> CreateClient<TInput, TOutput>() 
        where TInput : class 
        where TOutput : class
    {
        return _serviceProvider.GetRequiredService<IApiClient<TInput, TOutput>>();
    }
}

注册工厂

builder.Services.AddScoped<IApiClientFactory, ApiClientFactory>();

控制器使用示例

public class ProjectController : ControllerBase 
{ 
    private readonly IApiClientFactory _apiClientFactory;

    public ProjectController(IApiClientFactory apiClientFactory)
    {
        _apiClientFactory = apiClientFactory;
    }

    public async Task<IActionResult> ProcessData()
    {
        var client1 = _apiClientFactory.CreateClient<ClassA, ClassB>();
        var result1 = await client1.PostToEndPoint("/api/endpoint1", new ClassA());

        var client2 = _apiClientFactory.CreateClient<ClassC, ClassD>();
        var result2 = await client2.PostToEndPoint("/api/endpoint2", new ClassC());

        // ...业务逻辑处理
        return Ok();
    }
}

方案二:重构为非泛型客户端+泛型方法

如果所有API调用逻辑一致,可将泛型从类级别移至方法级别,仅需注入单个客户端实例。

非泛型接口与实现

public interface IApiClient
{
    Task<TOutput> PostToEndPoint<TInput, TOutput>(string url, TInput input) 
        where TInput : class 
        where TOutput : class;
}

public class ApiClient : IApiClient
{
    private readonly HttpClient _httpClient;

    public ApiClient(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<TOutput> PostToEndPoint<TInput, TOutput>(string url, TInput input) 
        where TInput : class 
        where TOutput : class
    {
        var response = await _httpClient.PostAsJsonAsync(url, input);
        response.EnsureSuccessStatusCode();
        var content = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<TOutput>(content);
    }
}

注册客户端

builder.Services.AddHttpClient<IApiClient, ApiClient>()
    .ConfigureHttpClient(client => 
    {
        client.BaseAddress = new Uri("https://your-api-base-url.com/");
    });

控制器使用示例

public class ProjectController : ControllerBase 
{ 
    private readonly IApiClient _apiClient;

    public ProjectController(IApiClient apiClient)
    {
        _apiClient = apiClient;
    }

    public async Task<IActionResult> ProcessData()
    {
        var result1 = await _apiClient.PostToEndPoint<ClassA, ClassB>("/api/endpoint1", new ClassA());
        var result2 = await _apiClient.PostToEndPoint<ClassC, ClassD>("/api/endpoint2", new ClassC());
        var result3 = await _apiClient.PostToEndPoint<ClassE, ClassF>("/api/endpoint3", new ClassE());

        // ...业务逻辑处理
        return Ok();
    }
}

方案对比

  • 方案一:保留原有泛型类结构,适合不同泛型参数的客户端需要独立配置(如不同BaseAddress、超时时间)的场景,通过工厂统一管理实例获取。
  • 方案二:代码更精简,减少DI容器中的实例数量,适合所有API调用逻辑完全一致的场景。

内容的提问来源于stack exchange,提问作者Sumit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:23:24