Mud.HttpUtils.Generator
2.0.0-preview2
See the version list below for details.
dotnet add package Mud.HttpUtils.Generator --version 2.0.0-preview2
NuGet\Install-Package Mud.HttpUtils.Generator -Version 2.0.0-preview2
<PackageReference Include="Mud.HttpUtils.Generator" Version="2.0.0-preview2" />
<PackageVersion Include="Mud.HttpUtils.Generator" Version="2.0.0-preview2" />
<PackageReference Include="Mud.HttpUtils.Generator" />
paket add Mud.HttpUtils.Generator --version 2.0.0-preview2
#r "nuget: Mud.HttpUtils.Generator, 2.0.0-preview2"
#:package Mud.HttpUtils.Generator@2.0.0-preview2
#addin nuget:?package=Mud.HttpUtils.Generator&version=2.0.0-preview2&prerelease
#tool nuget:?package=Mud.HttpUtils.Generator&version=2.0.0-preview2&prerelease
Mud.HttpUtils.Generator
概述
Mud.HttpUtils.Generator 是一个基于 Roslyn 的源代码生成器,自动为标记了 [HttpClientApi] 特性的接口生成 HttpClient 实现类和服务注册代码。支持多种 HTTP 方法、灵活的参数处理、内容类型管理、Token 认证(含 API Key / HMAC 签名模式)、请求体加密、流式响应、缓存、日志脱敏等功能。
功能特性
核心功能
- 自动代码生成:根据接口定义自动生成 HttpClient 实现
- HTTP 方法支持:支持 GET、POST、PUT、DELETE(含请求体)、PATCH、HEAD、OPTIONS 等 HTTP 方法
- 参数处理:自动处理 Path、Query、Header、Body、FormContent、Form、MultipartForm、Upload 等参数类型
- Token 管理:支持多种 Token 类型,TokenType 使用字符串类型,解耦强绑定
- HttpClient 模式:支持通过
HttpClient属性直接注入 HttpClient 接口,与TokenManage互斥 - 依赖注入:自动生成服务注册扩展方法
AddWebApiHttpClient() - 智能注释:根据运行模式自动生成 DI 依赖提示注释
- Timeout 生效:
[HttpClientApi(Timeout = N)]中的Timeout属性大于 0 时,生成器会在注册代码中生成client.Timeout设置
高级功能
- 内容类型管理:支持接口级、方法级、参数级的内容类型配置
- 请求/响应类型分离:支持请求和响应使用不同的内容类型
- 请求体加密:支持请求体数据加密传输
- 响应解密:支持响应数据自动解密
- 文件下载:支持大文件下载和二进制数据下载
- 文件上传进度:支持通过
IFormContent的ToHttpContentAsync(IProgress<long>)报告上传进度 - 表单数据:支持 multipart/form-data 格式,支持
[JsonPropertyName]属性名映射 - 数组查询参数:支持数组类型的查询参数
- 原始字符串请求体:支持
[Body(RawString = true)]直接发送原始字符串,支持[Body(UseStringContent = true)]发送字符串内容 - 继承支持:支持生成抽象类、类继承、接口继承
- 事件处理器生成:通过
[GenerateEventHandler]特性自动生成事件处理器代码 - 忽略生成:支持通过
[IgnoreGenerator]特性忽略特定代码生成(可标注接口、方法、属性、字段) - 缓存支持:识别
[Cache]特性,配合CacheResponseInterceptor实现响应缓存 - 安全认证:识别
TokenInjectionMode.ApiKey和TokenInjectionMode.HmacSignature模式 - 日志脱敏:识别
[SensitiveData]特性,配合ISensitiveDataMasker实现日志脱敏 - Token Scopes:识别
[Token(Scopes = "...")]特性,支持 OAuth2 令牌作用域
安装
dotnet add package Mud.HttpUtils.Generator
源代码生成器需配合运行时库
Mud.HttpUtils一起使用。
快速开始
1. 定义 API 接口
using Mud.HttpUtils.Attributes;
[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
public interface IUserApi
{
[Get("/users/{id}")]
Task<UserInfo> GetUserAsync([Path] int id);
[Post("/users")]
Task<UserInfo> CreateUserAsync([Body] CreateUserRequest request);
[Get("/users")]
Task<List<UserInfo>> GetUsersAsync([Query] string? name = null, [Query] int page = 1);
}
2. 注册服务
// 注册 HttpClient + 弹性策略
services.AddMudHttpUtils("userApi", "https://api.example.com");
// 注册生成器生成的 API 接口实现
services.AddWebApiHttpClient();
3. 使用 API
public class UserService
{
private readonly IUserApi _api;
public UserService(IUserApi api)
{
_api = api;
}
public async Task<UserInfo> GetUserAsync(int id)
{
return await _api.GetUserAsync(id);
}
}
三种运行模式
生成器根据 [HttpClientApi] 特性配置生成不同的实现代码:
模式一:默认模式(IMudAppContext)
不设置 TokenManage 和 HttpClient 时,构造函数依赖 IOptions<JsonSerializerOptions> 和 IMudAppContext。
[HttpClientApi]
public interface IMyApi { }
// 生成的构造函数:
// public MyApi(IOptions<JsonSerializerOptions> option, IMudAppContext appContext)
模式二:TokenManager 模式
设置 TokenManage 时,构造函数依赖 IOptions<JsonSerializerOptions> 和指定的 Token 管理器类型。
[HttpClientApi(TokenManage = "IFeishuAppManager")]
public interface IMyApi { }
// 生成的构造函数:
// public MyApi(IOptions<JsonSerializerOptions> option, IFeishuAppManager appManager)
模式三:HttpClient 模式(推荐)
设置 HttpClient 时,构造函数依赖 IOptions<JsonSerializerOptions> 和指定的 HttpClient 接口类型。不生成 Token 相关代码。
[HttpClientApi(HttpClient = "IEnhancedHttpClient")]
public interface IMyApi { }
// 生成的构造函数:
// public MyApi(IOptions<JsonSerializerOptions> option, IEnhancedHttpClient httpClient)
注意:
HttpClient与TokenManage互斥,同时定义时HttpClient优先。
生成的代码
实现类
对于接口 IUserApi,生成器会生成 UserApi 实现类,位于原始接口命名空间的 .HttpClientApi 子命名空间下:
namespace MyApp.HttpClientApi
{
internal partial class UserApi : IUserApi
{
// 构造函数和字段(根据运行模式不同而不同)
// 所有接口方法的实现
}
}
服务注册扩展方法
生成器会生成 HttpClientApiExtensions 类,包含 AddWebApiHttpClient() 扩展方法:
public static partial class HttpClientApiExtensions
{
public static IServiceCollection AddWebApiHttpClient(this IServiceCollection services)
{
// 注册 IUserApi 的 HttpClient 包装实现类(瞬时服务)
// 注意:实现类构造函数依赖 IEnhancedHttpClient,请确保已通过 AddMudHttpClient 等方法注册此服务
services.AddTransient<global::MyApp.IUserApi, global::MyApp.HttpClientApi.UserApi>();
return services;
}
}
Timeout 配置生成
当 [HttpClientApi(Timeout = N)] 中 Timeout > 0 时,生成器会在注册方法中添加 client.Timeout 设置:
[HttpClientApi(HttpClient = "IEnhancedHttpClient", Timeout = 50)]
public interface IMyApi { }
// 生成的注册代码:
services.AddTransient<global::MyApp.IMyApi>(sp =>
{
var httpClient = sp.GetRequiredService<global::Mud.HttpUtils.IEnhancedHttpClient>();
var client = httpClient as global::Mud.HttpUtils.HttpClientFactoryEnhancedClient;
if (client != null)
{
var innerClient = client.Client;
innerClient.Timeout = TimeSpan.FromMilliseconds(50000);
}
return new global::MyApp.HttpClientApi.MyApi(option, httpClient);
});
智能注释提示
生成器会根据运行模式自动生成 DI 依赖提示:
| 模式 | 生成的注释 |
|---|---|
| HttpClient | // 注意:实现类构造函数依赖 IEnhancedHttpClient,请确保已通过 AddMudHttpClient 等方法注册此服务 |
| TokenManager | // 注意:实现类构造函数依赖 IFeishuAppManager,请确保已注册此令牌管理器服务 |
| 默认 | // 注册 XX 的 HttpClient 包装实现类(瞬时服务) |
注册组
通过 RegistryGroupName 可以将多个接口的注册方法分组:
[HttpClientApi(RegistryGroupName = "External")]
public interface IExternalApi { }
[HttpClientApi(RegistryGroupName = "External")]
public interface IAnotherExternalApi { }
// 生成 AddExternalWebApiHttpClient() 方法
services.AddExternalWebApiHttpClient();
特性详解
HttpClientApi 特性
[HttpClientApi(
ContentType = "application/json", // 默认请求内容类型
Timeout = 50, // 超时时间(秒),默认 50
TokenManage = "ITokenManager", // Token 管理器接口(与 HttpClient 互斥)
HttpClient = "IMyHttpClient", // HttpClient 接口(与 TokenManage 互斥,优先)
RegistryGroupName = "Example", // 注册组名称
IsAbstract = false, // 是否生成抽象类
InheritedFrom = "BaseClass" // 继承的基类
)]
public interface IExampleApi { }
BaseAddress构造函数和属性已废弃,请通过AddMudHttpClient(clientName, baseAddress)配置基地址。
HTTP 方法特性
[Post(
"/api/users", // 请求路径
ContentType = "application/json", // 请求内容类型
ResponseContentType = "application/xml",// 响应内容类型
ResponseEnableDecrypt = false // 响应是否启用解密
)]
Task<UserInfo> CreateUserAsync([Body] UserRequest request);
内容类型优先级
Body 参数级 > 方法级 > 接口级 > 默认值 (application/json)
参数特性
Path 参数
[Get("/users/{id}/posts/{postId}")]
Task<Post> GetPostAsync([Path] int id, [Path] int postId);
Query 参数
[Get("/users")]
Task<List<User>> GetUsersAsync(
[Query] string? name = null,
[Query] int page = 1,
[Query] int pageSize = 20
);
数组 Query 参数
[Get("/users")]
Task<List<User>> GetUsersAsync(
[ArrayQuery] int[] ids, // 默认分号分隔
[ArrayQuery(Separator = ",")] string[] tags // 逗号分隔
);
Header 参数
[Get("/users")]
Task<User> GetUserAsync([Header("X-Custom-Header")] string customValue);
Body 参数
// 基本 Body 参数
[Post("/users")]
Task<User> CreateUserAsync([Body] UserRequest request);
// 指定内容类型
[Post("/users")]
Task<User> CreateUserAsync([Body("application/xml")] UserRequest request);
// 启用加密
[Post("/users")]
Task<User> CreateUserAsync(
[Body(
EnableEncrypt = true,
EncryptSerializeType = SerializeType.Json,
EncryptPropertyName = "data"
)] UserRequest request
);
// 原始字符串内容
[Post("/content")]
Task PostContentAsync([Body(RawString = true)] string content);
// 字符串内容(调用 ToString())
[Post("/text")]
Task SendTextAsync([Body(UseStringContent = true)] object message);
Form 参数(URL 编码表单字段)
[Post("/api/login")]
Task<LoginResult> LoginAsync(
[Form("username")] string user,
[Form("password")] string pass);
MultipartForm 参数(多部分表单字段)
[Post("/api/upload")]
Task<UploadResult> UploadFileAsync(
[MultipartForm] IFormFile file,
[MultipartForm] string description);
Upload 参数(文件上传)
// 基本文件上传
[Post("/api/upload")]
Task<UploadResult> UploadAsync([Upload] IFormFile file);
// 自定义字段名和文件名
[Post("/api/upload")]
Task<UploadResult> UploadDocumentAsync(
[Upload(FieldName = "document", FileName = "report.pdf")] IFormFile file);
// 指定内容类型
[Post("/api/upload")]
Task<UploadResult> UploadImageAsync(
[Upload(ContentType = "image/png")] IFormFile image);
FilePath 参数(文件下载)
[Get("/files/{fileId}")]
Task DownloadFileAsync([Path] string fileId, [FilePath(BufferSize = 81920)] string savePath);
FormContent 参数(表单数据)
[Post("/upload")]
Task UploadAsync([FormContent] IFormContent formData);
// 带上传进度
[Post("/upload")]
Task UploadAsync([FormContent] IFormContent formData, IProgress<long>? progress = null);
FormContentGenerator支持[JsonPropertyName]特性,当属性标记了[JsonPropertyName("custom_name")]时,生成的表单字段名使用custom_name而非 C# 属性名。IFormContent.ToHttpContentAsync(IProgress<long>?)支持上传进度报告。
Token 认证
// 接口级设置 Token 类型
[Token("TenantAccessToken")]
public interface IMyApi { }
// 方法级设置 Token 类型
[Get("/api/user/profile")]
[Token("UserAccessToken", Scopes = "user:read")]
Task<Profile> GetProfileAsync();
// 参数级设置 Token 类型
[Get("/users/{id}")]
Task<User> GetUserAsync([Path] int id, [Token("UserAccessToken")] string? token = null);
// Token 注入模式
[Token("AppAccessToken", InjectionMode = TokenInjectionMode.Header, Name = "Authorization")]
// Token 作用域
[Token("UserAccessToken", Scopes = "user:read,user:write")]
Token 注入模式:
| 模式 | 说明 |
|---|---|
Header |
注入到 HTTP Header(默认) |
Query |
注入到 URL Query 参数 |
Path |
注入到 URL Path |
ApiKey |
API Key 认证,通过 IApiKeyProvider 获取密钥注入到请求头 |
HmacSignature |
HMAC 签名认证,通过 IHmacSignatureProvider 计算签名注入到请求头 |
缓存支持
[Get("/users/{id}")]
[Cache(60, VaryByUser = true)]
Task<User> GetUserAsync([Path] int id);
[Get("/config")]
[Cache(300, CacheKeyTemplate = "config:{0}", UseSlidingExpiration = true, Priority = CachePriority.High)]
Task<Config> GetConfigAsync();
[Cache]特性标记的方法,配合CacheResponseInterceptor实现响应缓存。CacheAttribute支持DurationSeconds、CacheKeyTemplate、VaryByUser、UseSlidingExpiration、Priority属性。
日志脱敏
public class UserRequest
{
public string Name { get; set; }
[SensitiveData(MaskMode = SensitiveDataMaskMode.Mask, PrefixLength = 3, SuffixLength = 4)]
public string IdCard { get; set; }
[SensitiveData(MaskMode = SensitiveDataMaskMode.Hide)]
public string Password { get; set; }
}
[SensitiveData]特性标记的属性,配合ISensitiveDataMasker在日志输出时自动脱敏。支持Hide(完全隐藏)、Mask(部分遮盖)、TypeOnly(仅显示类型)三种脱敏模式。
响应解密
[Post("/api/secure-data", ResponseEnableDecrypt = true)]
Task<SecureData> GetSecureDataAsync([Body] Request request);
继承支持
// 生成抽象类
[HttpClientApi(IsAbstract = true)]
public interface IBaseApi
{
[Get("/entities/{id}")]
Task<Entity> GetEntityAsync([Path] string id);
}
// 继承自指定基类
[HttpClientApi(InheritedFrom = "BaseApiClass")]
public interface IUserApi : IBaseApi
{
[Get("/users")]
Task<List<User>> GetUsersAsync();
}
事件处理器生成
[GenerateEventHandler(
EventType = "UserCreatedEvent",
HandlerClassName = "UserCreatedEventHandler",
HandlerNamespace = "MyApp.Handlers",
InheritedFrom = "BaseEventHandler",
ConstructorParameters = "ILogger logger, IEmailService emailService",
ConstructorBaseCall = "logger"
)]
public class UserCreatedEvent
{
public string UserId { get; set; }
public string UserName { get; set; }
}
忽略代码生成
// 忽略接口生成(跳过实现类和注册代码)
[IgnoreGenerator]
[HttpClientApi]
public interface IInternalApi { }
// 忽略方法实现
[IgnoreGenerator]
[Post("/internal")]
Task InternalMethodAsync([Body] object data);
// 忽略属性/字段
public class UserRequest
{
public string Name { get; set; }
[IgnoreGenerator]
public string InternalField { get; set; }
}
项目结构
Mud.HttpUtils.Generator/
├── Analyzers/ # 代码分析器
│ ├── MethodAnalyzer.cs # 方法分析
│ └── ParameterAnalyzer.cs # 参数分析
├── Generators/ # 代码生成器
│ ├── Implementation/ # 实现类生成
│ │ ├── ConstructorGenerator.cs # 构造函数生成
│ │ └── RequestBuilder.cs # 请求构建
│ ├── FormContentGenerator.cs # FormContent 生成器(支持 JsonPropertyName)
│ ├── HttpInvokeClassSourceGenerator.cs # 实现类主生成器
│ └── HttpInvokeRegistrationGenerator.cs # 注册代码生成器(含 Timeout 配置)
├── Helpers/ # 辅助类
│ ├── AttributeDataHelper.cs # 特性数据辅助
│ ├── AttributeSyntaxHelper.cs # 特性语法辅助
│ └── ...
├── Models/ # 数据模型
│ ├── Analysis/ # 分析结果模型
│ └── Metadata/ # 元数据模型
│ ├── HttpClientApiInfo.cs # API 接口信息(含 HttpClientType/TokenManagerType/Timeout)
│ └── HttpClientApiInfoBase.cs # 基础 API 信息
└── Validators/ # 验证器
依赖项
- .NET Standard 2.0
- Microsoft.CodeAnalysis.Analyzers
- Microsoft.CodeAnalysis.CSharp
- Mud.HttpUtils.Abstractions(项目引用)
- Mud.HttpUtils.Attributes(项目引用)
调试生成的代码
在项目文件中添加以下配置,保留生成的源代码:
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
生成的代码位于 obj/Debug/<tfm>/generated/Mud.HttpUtils.Generator/ 目录下。
版本历史
2.0.0
- 注册代码生成新增智能注释提示:HttpClient 模式提示
AddMudHttpClient,TokenManager 模式提示注册令牌管理器 HttpClientApiInfo新增HttpClientType和TokenManagerType属性- 新增事件处理器生成功能
- 新增继承支持
- 新增忽略生成功能
TokenAttribute.TokenType改为字符串类型- 新增
HttpClient属性 HttpClient与TokenManage互斥- 新增
TokenInjectionMode.ApiKey和TokenInjectionMode.HmacSignature安全认证模式 - 新增
[Cache]特性识别,配合CacheResponseInterceptor实现响应缓存 - 新增
[SensitiveData]特性识别,配合ISensitiveDataMasker实现日志脱敏 - 新增
TokenAttribute.Scopes属性,支持 OAuth2 令牌作用域 - 新增
IFormContent.ToHttpContentAsync(IProgress<long>?)上传进度报告支持
1.7.0
- 初始版本
- 从 Mud.ServiceCodeGenerator 项目中独立出来
相关项目
- Mud.HttpUtils - 运行时库(元包)
- Mud.HttpUtils.Abstractions - 接口定义
- Mud.HttpUtils.Attributes - 特性定义
- Mud.HttpUtils.Client - 客户端实现
- Mud.HttpUtils.Resilience - 弹性策略
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-rc2 | 122 | 5/13/2026 |
| 2.0.0-rc1 | 163 | 5/9/2026 |
| 2.0.0-preview6 | 125 | 5/6/2026 |
| 2.0.0-preview5 | 99 | 5/3/2026 |
| 2.0.0-preview4 | 187 | 4/30/2026 |
| 2.0.0-preview3 | 90 | 4/29/2026 |
| 2.0.0-preview2 | 120 | 4/28/2026 |
| 2.0.0-preview1 | 92 | 4/27/2026 |
| 1.7.1 | 240 | 5/12/2026 |
| 1.7.0 | 397 | 4/12/2026 |
| 1.6.7 | 106 | 4/11/2026 |
| 1.6.6 | 143 | 4/8/2026 |
| 1.6.5 | 147 | 4/5/2026 |
| 1.6.4 | 107 | 4/2/2026 |
| 1.6.3 | 107 | 3/21/2026 |
| 1.6.2 | 114 | 3/17/2026 |
| 1.6.1 | 110 | 3/16/2026 |
| 1.6.0 | 117 | 3/13/2026 |