ITPub博客

首页 > 应用开发 > Html/css > 是直观的接口、丰富的智能提示,还是无需深挖源码即可上手的文档

是直观的接口、丰富的智能提示,还是无需深挖源码即可上手的文档

投稿 Html/css 作者:ecclw459 时间:2026-01-13 17:05:58 0 删除 编辑

Mud.Feishu 通过特性系统定义 API 契约,编译器自动生成强类型 HTTP 客户端实现。

// 元数据驱动API定义[HttpClientApi(
    RegistryGroupName = "Organization",
    TokenManage = nameof(ITenantTokenManager),
    Timeout = 50
)]
[Header(Consts.Authorization)]public interface IFeishuTenantV3User{
    [Get("/open-apis/contact/v3/users/{user_id}")]
    Task<FeishuApiResult<GetUserInfoResult>?> GetUserInfoByIdAsync(
        [Path] string user_id,
        [Query] string? user_id_type = null);
    [Post("/open-apis/contact/v3/users")]
    Task<FeishuApiResult<CreateOrUpdateUserResult>?> CreateUserAsync(
        [Body] CreateUserRequest userModel,
        [Query("user_id_type")] string? user_id_type = Consts.User_Id_Type);
}

特性体系详解

1. HttpClientApi 特性(接口级)

/// <summary>/// HTTP客户端API特性,用于标记需要生成HTTP客户端包装类的接口/// </summary>[AttributeUsage(AttributeTargets.Interface, AllowMultiple = false)]internal class HttpClientApiAttribute : Attribute{    /// <summary>
    /// HTTP请求的内容类型,默认 "application/json"
    /// </summary>
    public string ContentType { get; set; } = "application/json";    /// <summary>
    /// HTTP连接超时时间(秒),默认50秒
    /// </summary>
    public int Timeout { get; set; } = 50;    /// <summary>
    /// 服务注册的分组名称
    /// </summary>
    public string? RegistryGroupName { get; set; }    /// <summary>
    /// 令牌管理服务接口的名称
    /// </summary>
    public string? TokenManage { get; set; }    /// <summary>
    /// 生成的客户端类是否为抽象类
    /// </summary>
    public bool IsAbstract { get; set; }    /// <summary>
    /// 生成的客户端类继承自哪个类
    /// </summary>
    public string? InheritedFrom { get; set; }
}

2. HTTP 方法特性(方法级)

HTTP 方法特性

GET

POST

PUT

DELETE

PATCH

HEAD

OPTIONS

查询资源

创建资源

更新资源

删除资源

部分更新

获取元数据

获取允许方法

3. 参数绑定特性(参数级)

特性 说明 示例
[Path] 绑定到URL路径参数 {user_id}
[Query] 绑定到查询字符串 ?page_size=10
[Body] 绑定到请求体 JSON 请求体
[Header] 绑定到请求头 Authorization: Bearer xxx
[Token] 自动附加认证令牌 自动获取令牌管理器

技术特点

  • 基于 Source Generator 的编译时代码生成
  • 支持完整的 HTTP 方法语义(GET/POST/PUT/DELETE/PATCH)
  • 参数自动绑定(Path/Query/Body/Header/Token)
  • 自动令牌管理集成

2.2 分层接口设计模式

Mud.Feishu 采用三层接口设计模式,实现清晰的职责划分和灵活的扩展能力。

接口层级架构

基础抽象层
IsAbstract=true

通用查询方法

支持多种令牌类型

具体实现层

租户令牌接口
TenantTokenManager

用户令牌接口
UserTokenManager

应用令牌接口
AppTokenManager

模块化扩展

Organization 模块

Message 模块

ChatGroup 模块

Approval 模块

Task 模块

Card 模块

其它 模块

接口继承关系示例

// 基础抽象接口[HttpClientApi(IsAbstract = true, InheritedFrom = nameof(FeishuV3User))]public interface IFeishuV3User{    // 通用查询方法
    [Get("/open-apis/contact/v3/users/{user_id}")]
    Task<FeishuApiResult<GetUserInfoResult>?> GetUserInfoByIdAsync(
        [Path] string user_id,
        [Query] string? user_id_type = null);
}// 租户令牌接口[HttpClientApi(TokenManage = nameof(ITenantTokenManager),
               RegistryGroupName = "Organization",
               InheritedFrom = nameof(FeishuV3User))]
[Header(Consts.Authorization)]public interface IFeishuTenantV3User : IFeishuV3User{    // 租户特有的方法:创建、更新、删除用户
    [Post("/open-apis/contact/v3/users")]
    Task<FeishuApiResult<CreateOrUpdateUserResult>?> CreateUserAsync(
        [Body] CreateUserRequest userModel);
    [Patch("/open-apis/contact/v3/users/{user_id}")]
    Task<FeishuNullDataApiResult?> UpdateUserAsync(
        [Path] string user_id,
        [Body] UpdateUserRequest userModel);
}// 用户令牌接口[HttpClientApi(TokenManage = nameof(IUserTokenManager),
               RegistryGroupName = "Organization",
               InheritedFrom = nameof(FeishuV3User))]
[Header(Consts.Authorization)]public interface IFeishuUserV3User : IFeishuV3User{    // 用户特有的方法:更新个人信息
    [Patch("/open-apis/contact/v3/users/{user_id}")]
    Task<FeishuNullDataApiResult?> UpdateMyProfileAsync(
        [Path] string user_id,
        [Body] UpdateUserRequest userModel);
}

2.3 代码生成工作流程

依赖注入容器生成的实现类Source GeneratorCSharp编译器接口定义代码开发者依赖注入容器生成的实现类Source GeneratorCSharp编译器接口定义代码开发者定义接口并应用特性1编译项目2触发代码生成3分析接口和方法签名4生成 HTTP 客户端类5返回生成代码6注册生成的服务7可注入使用8

代码生成示例

原始接口定义:

[HttpClientApi(TokenManage = nameof(ITenantTokenManager),
               RegistryGroupName = "Organization")]
[Header(Consts.Authorization)]public interface IFeishuTenantV3User{
    [Get("/open-apis/contact/v3/users/{user_id}")]
    Task<FeishuApiResult<GetUserInfoResult>?> GetUserInfoByIdAsync(
        [Path] string user_id,
        [Query] string? user_id_type = null);
}

生成的实现类:

internal class FeishuTenantV3User : IFeishuTenantV3User{    private readonly IEnhancedHttpClient _httpClient;    private readonly ITokenManager _tokenManager;    public FeishuTenantV3User(
        IEnhancedHttpClient httpClient,
        ITenantTokenManager tokenManager)
    {
        _httpClient = httpClient;
        _tokenManager = tokenManager;
    }    public async Task<FeishuApiResult<GetUserInfoResult>?> GetUserInfoByIdAsync(        string user_id,        string? user_id_type = null,
        CancellationToken cancellationToken = default)
    {        string access_token = await _tokenManager.GetTokenAsync();        if (string.IsNullOrEmpty(access_token))
        {            throw new InvalidOperationException("无法获取访问令牌");
        }        if (string.IsNullOrEmpty(user_id))
        {            throw new ArgumentNullException("user_id");
        }
        user_id = user_id.Trim();        string url = "/open-apis/contact/v3/users/" + user_id;        using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
        NameValueCollection queryParams = HttpUtility.ParseQueryString(string.Empty);        if (!string.IsNullOrEmpty(user_id_type))
        {            string encodedValue = HttpUtility.UrlEncode(user_id_type);
            queryParams.Add("user_id_type", encodedValue);
        }        if (!string.IsNullOrEmpty(department_id_type))
        {            string encodedValue2 = HttpUtility.UrlEncode(department_id_type);
            queryParams.Add("department_id_type", encodedValue2);
        }        if (queryParams.Count > 0)
        {
            _ = url + "?" + queryParams.ToString();
        }
        request.Headers.Add("Authorization", access_token);        return await _httpClient.SendAsync<FeishuApiResult<GetUserInfoResult>>(request, cancellationToken);
    }
}

三、服务注册架构

3.1 模块化注册策略

Mud.Feishu 提供灵活的服务注册方式,支持按需引入功能模块。

方式一:建造者模式(推荐)

// 构建者模式提供流畅APIbuilder.Services.AddFeishuServices()
    .ConfigureFrom(configuration)
    .AddOrganizationApi()    // 组织管理
    .AddMessageApi()        // 消息服务
    .AddTokenManagers()     // 令牌管理
    .Build();

方式二:枚举模块注册

// 按枚举模块注册services.AddFeishuModules(
    configuration,
    FeishuModule.Organization,
    FeishuModule.Message
);

方式三:快速注册方法

// 快速注册令牌管理器services.AddFeishuTokenManagers(configuration);// 快速注册所有服务services.AddFeishuAllServices(configuration);

3.2 服务注册流程图

建造者模式

枚举模块

快速注册

开始服务注册

选择注册方式

AddFeishuServices

AddFeishuModules

AddFeishuAllServices

ConfigureFrom
配置绑定

添加功能模块

AddOrganizationApi

AddMessageApi

AddChatGroupApi

AddApprovalApi

AddTaskApi

AddCardApi

AddFeishuHttpClient
AddTokenManagers
AddOrganizationWebApiHttpClient

AddFeishuHttpClient
AddTokenManagers
AddMessageWebApiHttpClient

AddFeishuHttpClient
AddTokenManagers
AddChatGroupWebApiHttpClient

AddFeishuHttpClient
AddTokenManagers
AddApprovalWebApiHttpClient

AddFeishuHttpClient 
AddTokenManagers  
AddTaskWebApiHttpClient

AddFeishuHttpClient
AddTokenManagers
AddCardsWebApiHttpClient

Build
验证配置
服务注册

服务注册完成

3.3 配置管理

FeishuOptions 配置类

/// <summary>/// 飞书 API 配置选项类/// </summary>public class FeishuOptions{    /// <summary>
    /// 飞书应用唯一标识,创建应用后获得
    /// 示例值: "cli_a1b2c3d4e5f6g7h8"
    /// </summary>
    public required string? AppId { get; set; }    /// <summary>
    /// 应用秘钥,创建应用后获得
    /// 示例值: "dskLLdkasdjlasdKK"
    /// </summary>
    public required string? AppSecret { get; set; }    /// <summary>
    /// 飞书 API 基础地址
    /// 默认值: "https://open.feishu.cn"
    /// </summary>
    public string? BaseUrl { get; set; }    /// <summary>
    /// HTTP 请求超时时间(秒)
    /// 默认值:30秒
    /// </summary>
    public string? TimeOut { get; set; }    /// <summary>
    /// 失败重试次数
    /// 默认值:3次
    /// </summary>
    public int? RetryCount { get; set; xbyzbw.cn}/// <summary>
    /// 是否启用日志记录,默认为true
    /// </summary>
    public bool EnableLogging { get; set; } = true;
}

appsettings.json 配置示例

{
  "Feishu": {
    "AppId": "cli_appid",
    "AppSecret": "dskxxxxxx",
    "BaseUrl": "https://open.feishu.cn",
    "TimeOut": "60",
    "RetryCount":nbaol.cn  3,
    "EnableLogging": true,
    "WebSocket":xjzbvs.cn {
      "AutoReconnect": true,
      "MaxReconnectAttempts": 5,
      "ReconnectDelayMs": 5000,
      "HeartbeatIntervalMs": 30000,
      "ConnectionTimeoutMs": 10000,
      "ReceiveBufferSize": 4096,
      "EnableLogging": true,
      "EnableMessageQueue": true,
      "MessageQueueCapacity": 1000,
      "ParallelMultiHandlers": true
    },
    "Webhook": {
      "RoutePrefix": "feishu/Webhook",
      "AutoRegisterEndpoint": true,
      "VerificationToken": "your_verification_token",
      "EncryptKey": xjzbbs.cn"your_encrypt_key",
      "EnableRequestLogging": true,
      "EnableExceptionHandling": true,
      "EventHandlingTimeoutMs": 30000,
      "MaxConcurrentEvents": 10
    }
  }}

配置验证机制

/// <summary>/// 构建服务注册,包含配置验证/// </summary>public IServiceCollection Build(){    // 验证配置
    if (!_configuration.IsConfigured)
    {        throw new InvalidOperationException(            "必须先配置 FeishuOptions,请使用 ConfigureFrom 或 ConfigureOptions 方法。");
    }    // 验证至少添加了一个服务
    if (!_configuration.HasAnyService())
    {        throw new InvalidOperationException(            "至少需要添加一个服务,请使用相应的 Add 方法。");
    }    // 添加配置验证
    _services.AddOptions<FeishuOptions>()
            .Validate(options => ValidateFeishuOptionsInternal(options),                "飞书服务需要在配置文件中正确配置 AppId 和 AppSecret。")
            .ValidateOnStart();    return _services;
}/// <summary>/// 内部验证飞书选项的方法///xjsczb.cn </summary>private static bool ValidateFeishuOptionsInternal(FeishuOptions options) =>
    !string.IsNullOrEmpty(options.AppId) && !string.IsNullOrEmpty(options.AppSecret);


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3107819/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102111