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

如何在ASP.NET Core中构建可注入的层级式Rest服务模拟类

实现链式调用的REST服务类及ASP.NET Core依赖注入方案

1. 核心类结构设计

核心思路是让根服务类作为入口,内部包含各个资源模块的子服务实例,子服务共享根服务的配置(比如apiKey)和HTTP客户端,以此实现Service.Users.GetUserById这类链式调用。

根服务类

public class ApiService
{
    public UsersService Users { get; }
    public GamesService Games { get; }

    // 构造函数接收配置与HTTP客户端,同时初始化所有子服务
    public ApiService(string apiKey, HttpClient httpClient)
    {
        Users = new UsersService(apiKey, httpClient);
        Games = new GamesService(apiKey, httpClient);
    }
}

资源子服务类(以UsersService为例)

每个子服务封装对应资源的所有操作,通过构造函数获取共享的apiKey和HttpClient:

public class UsersService
{
    private readonly string _apiKey;
    private readonly HttpClient _httpClient;

    public UsersService(string apiKey, HttpClient httpClient)
    {
        _apiKey = apiKey;
        _httpClient = httpClient;
    }

    public async Task<User> GetUserById(string userId)
    {
        // 配置请求头(后续可统一移到HttpClient配置中)
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", _apiKey);
        var response = await _httpClient.GetAsync($"users/{userId}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<User>();
    }
}

GamesService实现

public class GamesService
{
    private readonly string _apiKey;
    private readonly HttpClient _httpClient;

    public GamesService(string apiKey, HttpClient httpClient)
    {
        _apiKey = apiKey;
        _httpClient = httpClient;
    }

    public async Task<List<Game>> GetList()
    {
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", _apiKey);
        var response = await _httpClient.GetAsync("games");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<List<Game>>();
    }
}

实体类示例

public class User
{
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Game
{
    public string Id { get; set; }
    public string Title { get; set; }
}

2. ASP.NET Core依赖注入配置

要让服务支持DI,需要在Program.cs中完成服务注册,同时处理apiKey的传递和HttpClient的复用。

方式1:直接指定apiKey注册

var builder = WebApplication.CreateBuilder(args);

// 注册HttpClient,配置API基础地址
builder.Services.AddHttpClient<ApiService>(client =>
{
    client.BaseAddress = new Uri("https://your-rest-api-base-url/");
});

// 注册ApiService,传入apiKey(可替换为从配置读取)
builder.Services.AddSingleton<ApiService>(sp =>
{
    var httpClient = sp.GetRequiredService<IHttpClientFactory>().CreateClient(nameof(ApiService));
    var apiKey = "your-api-key-here"; // 或用 builder.Configuration["ApiSettings:ApiKey"] 从配置读取
    return new ApiService(apiKey, httpClient);
});

var app = builder.Build();

方式2:通过配置文件读取apiKey

先在appsettings.json中添加配置:

{
  "ApiSettings": {
    "ApiKey": "your-actual-api-key",
    "BaseUrl": "https://your-rest-api-base-url/"
  }
}

定义配置绑定类:

public class ApiSettings
{
    public string ApiKey { get; set; }
    public string BaseUrl { get; set; }
}

然后在Program.cs中注册:

var builder = WebApplication.CreateBuilder(args);

// 绑定配置文件中的ApiSettings
builder.Services.Configure<ApiSettings>(builder.Configuration.GetSection("ApiSettings"));

// 注册HttpClient,从配置读取基础地址和apiKey
builder.Services.AddHttpClient<ApiService>((sp, client) =>
{
    var settings = sp.GetRequiredService<IOptions<ApiSettings>>().Value;
    client.BaseAddress = new Uri(settings.BaseUrl);
    // 统一设置Authorization头,避免每个子服务重复写
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", settings.ApiKey);
});

// 注册ApiService
builder.Services.AddSingleton<ApiService>(sp =>
{
    var httpClient = sp.GetRequiredService<IHttpClientFactory>().CreateClient(nameof(ApiService));
    var settings = sp.GetRequiredService<IOptions<ApiSettings>>().Value;
    return new ApiService(settings.ApiKey, httpClient);
});

var app = builder.Build();

在Controller中使用

public class DemoController : ControllerBase
{
    private readonly ApiService _apiService;

    // 通过构造函数注入ApiService
    public DemoController(ApiService apiService)
    {
        _apiService = apiService;
    }

    [HttpGet("user/{userId}")]
    public async Task<IActionResult> GetUser(string userId)
    {
        var user = await _apiService.Users.GetUserById(userId);
        return Ok(user);
    }

    [HttpGet("games")]
    public async Task<IActionResult> GetGames()
    {
        var games = await _apiService.Games.GetList();
        return Ok(games);
    }
}

3. 优化建议

  • 统一配置请求头:把Authorization头的设置移到HttpClient的注册逻辑中,避免每个子服务方法重复编写。
  • 子服务也注册到DI:如果后续子服务需要依赖其他DI服务,可以把子服务也注册到容器,让根服务通过构造函数注入子服务,而不是自行new:
    // 修改ApiService构造函数
    public ApiService(UsersService usersService, GamesService gamesService)
    {
        Users = usersService;
        Games = gamesService;
    }
    
    // 注册子服务
    builder.Services.AddSingleton<UsersService>(sp =>
    {
        var httpClient = sp.GetRequiredService<IHttpClientFactory>().CreateClient(nameof(ApiService));
        var settings = sp.GetRequiredService<IOptions<ApiSettings>>().Value;
        return new UsersService(settings.ApiKey, httpClient);
    });
    
    builder.Services.AddSingleton<GamesService>(sp =>
    {
        var httpClient = sp.GetRequiredService<IHttpClientFactory>().CreateClient(nameof(ApiService));
        var settings = sp.GetRequiredService<IOptions<ApiSettings>>().Value;
        return new GamesService(settings.ApiKey, httpClient);
    });
    
    // 注册根服务
    builder.Services.AddSingleton<ApiService>();
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 17:55:00