NexusContract.Aligner
1.0.0-preview.19
dotnet tool install --global NexusContract.Aligner --version 1.0.0-preview.19
dotnet new tool-manifest
dotnet tool install --local NexusContract.Aligner --version 1.0.0-preview.19
#tool dotnet:?package=NexusContract.Aligner&version=1.0.0-preview.19&prerelease
nuke :add-package NexusContract.Aligner --version 1.0.0-preview.19
NexusContract.Aligner
OpenAPI → 点号字段(dot-notation)→ C# 契约生成器(简洁、可定制、生产可用)
目标
将 OpenAPI/Swagger 文档的复杂嵌套结构展平为 dot-notation 字段路径,并生成清晰、可编译的 C# Request/Response POCO。目标是生成可直接用于生产、易于维护且便于二次定制的契约代码。
快速开始 ✅
本地生成(开发):
cd src/NexusContract.Aligner
dotnet build
# 运行示例(本地 Swagger 服务)
dotnet run -- -s http://localhost:5000/swagger/v1/swagger.json -o /tmp/gen -n DemoGen
作为已发布工具(示例):
nxc-align -s <source> -o <output> -n <root-namespace> [-m <module>]
CLI 参数
-s|--source(string, required): OpenAPI 文档 URL 或本地文件路径-o|--output(string): 输出目录(默认:./NexusContracts)-n|--namespace(string): 根命名空间(默认:NexusContract.Generated)-m|--module(string): 按 OpenAPI Tag 过滤模块--list(flag): 列出所有可用的模块和接口(不生成代码)--debug(flag): 启用调试模式(详细诊断)
模板与定制
- 模板文件:
src/NexusContract.Aligner/Templates/ContractTemplate.scriban - 优先级:工具运行时会优先加载外部
.scriban(csproj已配置为 CopyToOutputDirectory);若外部模板不可用,工具将回退到内联模板。 - 修改流程:编辑外部模板 →
dotnet build(确保复制)→ 重新运行生成命令。 - 内联模板仅作为打包工具时的 fallback,建议在开发期间使用外部模板以便热修改与版本控制。
生成代码约定
- 请求类:
{Pascal(OperationId)}Request,实现IApiRequest<{Type}Response>、IContractValidator、IContractNormalizer(Normalize 仅做标准化,Validate 仅包含物理硬约束) - 响应类:
{Pascal(OperationId)}Response,纯 POCO,不包含验证逻辑 - 字段注释:优先使用 OpenAPI 的
description;若无,则使用物理路径(例如merchantOrderNo)作为注释文本 - 不生成冗余默认属性(例如 EmitBehavior.Default),仅在必要情况下写出
IsRequired = true
示例:Alipay
生成命令示例:
nxc-align -s http://localhost:5000/swagger/v1/swagger.json -o ./gen -n DemoGen -m alipay
生成样例(截取):
[ApiOperation("alipay.trade.pay", interaction: InteractionKind.RequestResponse)]
public partial class AlipayTradePayRequest : IApiRequest<AlipayTradePayResponse>, IContractValidator, IContractNormalizer
{
/// <summary>merchantOrderNo</summary>
[ApiField("merchantOrderNo")]
public string Merchantorderno { get; set; }
// ...
}
开发与调试指南
- 常见入口:
SwaggerParser.cs:解析 OpenAPI、展平 Schema、构建ContractGenerationModelCodeGenerator.cs:加载模板并渲染输出Templates/ContractTemplate.scriban:主模板,直接影响最终代码样式
- 验证生成:
- 修改模板或解析逻辑
dotnet build(确保外部模板被复制)- 运行生成命令,检查
/tmp/gen输出
- 常见问题排查:
- “模板修改无效”:确认外部模板已复制到输出目录(
dotnet build) - “字段缺失”:检查
SwaggerParser.FlattenSchema对$ref和循环引用的处理 - “类名包含非法字符”:
ContractGenerationModel将 OperationId 转为 PascalCase(支持.,_,-)
- “模板修改无效”:确认外部模板已复制到输出目录(
CI 集成建议
将生成步骤加入 CI(Workflow 或脚本),并在生成后自动提交 src/Generated:
- 触发器:push/openapi 目录变更或手动 workflow_dispatch
- 步骤:checkout → setup-dotnet → build/publish工具 → 生成 → commit & push
变更记录(近期重要修复)
- 支持外部模板复制(
csproj已配置) - 修复:使用
Summary(点号)作为业务意图显示而非 Swagger 下划线operationId - 修复:生成类命名(
.→ PascalCase 转换) - 修复:字段注释、Normalize 注释改为
//、响应字段缩进不一致问题
贡献
欢迎 PR 与 Issue。请保证变更包含描述、单元测试(若需要)和更新的 README 或变更日志。
许可证
MIT(详见仓库根目录 LICENSE)
(如需更详细的产品文档或历史文档,请在 PR 中注明,我可以从历史提交中提取并整理精要)
特性
✨ 递归展平算法 - 自动将深层嵌套的 OpenAPI 对象转换为 a.b.c 点号路径
🔄 双源支持 - 支持远程 URL(HTTPS)和本地文件加载
🎯 模块过滤 - 按 OpenAPI Tag 过滤特定模块
🔧 自动代码生成 - 使用 Scriban 模板生成 .NET Standard 2.0 兼容代码
📊 完整类型映射 - OpenAPI 类型自动映射到 C# 类型
🎨 智能文件组织 - 按模块自动创建子文件夹结构
安装
作为 .NET 工具全局安装
dotnet tool install --global NexusContract.Aligner
作为本地工具安装
dotnet tool install NexusContract.Aligner --local
从源码编译
cd src/NexusContract.Aligner
dotnet publish -c Release
快速开始
基本用法
nxc-align \
-s https://api.example.com/swagger.json \
-o ./GeneratedContracts \
-ns MyApp.Contracts
实际例子:宠物店 API
第 1 步:预览所有模块
nxc-align -s https://petstore.swagger.io/v2/swagger.json --list
输出显示有 3 个模块:pet、store、user,共 20 个接口
第 2 步:预览特定模块(如 pet)
nxc-align -s https://petstore.swagger.io/v2/swagger.json --list -m pet
输出显示 pet 模块有 8 个接口,其中 AddANewPetToTheStore 有 7 个字段
第 3 步:生成代码
nxc-align \
-s https://petstore.swagger.io/v2/swagger.json \
-o ./PetStore.Contracts \
-ns "MyPetApp.Contracts" \
-m pet
生成文件在 ./PetStore.Contracts/Pet/ 目录下
从本地文件生成
nxc-align \
-s ./local-openapi.json \
-o ./Contracts \
-ns "MyCompany.ApiContracts"
查看可用模块和接口
生成前先预览 API 有哪些模块和接口:
# 显示所有模块和接口
nxc-align -s https://api.example.com/swagger.json --list
# 显示特定模块的接口
nxc-align -s https://api.example.com/swagger.json --list -m Transactions
CLI 参数
| 参数 | 短形式 | 类型 | 必需 | 说明 |
|---|---|---|---|---|
--source |
-s |
string | ✅ | OpenAPI 文档源(URL 或本地文件路径) |
--output |
-o |
string | ❌ | 输出目录(默认:./NexusContracts) |
--namespace |
-ns |
string | ❌ | 生成代码的基础命名空间(默认:NexusContract.Generated) |
--module |
-m |
string | ❌ | 模块过滤器(OpenAPI 中的 Tag 名称) |
--list |
flag | ❌ | 列出所有可用模块和接口(不生成代码) | |
--debug |
flag | ❌ | 启用调试模式(详细诊断) |
工作原理
1. 递归展平算法
OpenAPI 中的嵌套结构:
{
"user": {
"profile": {
"name": "string",
"email": "string"
},
"settings": {
"language": "string"
}
}
}
被转换为点号路径:
user.profile.name
user.profile.email
user.settings.language
2. 类型映射
OpenAPI 类型自动映射到 C# 类型:
| OpenAPI 类型 | C# 类型 | 备注 |
|---|---|---|
number (double) |
double |
|
number (decimal/null) |
decimal |
默认映射 |
integer |
int |
|
integer (int64) |
long |
|
string |
string |
|
string (date-time) |
DateTime |
|
string (uuid) |
Guid |
|
boolean |
bool |
|
array |
List<T> |
T 为元素类型 |
3. 代码生成
生成的代码示例(完全符合 .NET Standard 2.0):
// <auto-generated> NXC-Aligner 颗粒度对齐工具生成 </auto-generated>
namespace MyApp.Contracts.Transactions;
using System;
using System.Collections.Generic;
using NexusContract.Abstractions;
using NexusContract.Abstractions.Attributes;
/// <summary>
/// 业务意图: CreateTransaction
/// HTTP POST /api/transactions
/// </summary>
[ApiOperation("CreateTransaction", interaction: InteractionKind.RequestResponse)]
public partial class CreateTransactionRequest : IApiRequest<CreateTransactionResponse>
{
/// <summary>
/// [TODO] 用户 ID
/// [物理路径] user.id
/// </summary>
[ApiField("user.id")]
public string UserId { get; set; }
/// <summary>
/// [TODO] 用户名称
/// [物理路径] user.profile.name
/// </summary>
[ApiField("user.profile.name")]
public string UserProfileName { get; set; }
public void Validate()
{
// 结构已对齐,请在此处补充物理熔断逻辑
}
}
/// <summary>
/// 纯 POCO:无接口约束,仅作数据容器
/// </summary>
public partial class CreateTransactionResponse
{
public string? Code { get; set; }
public string? Message { get; set; }
}
架构设计
核心模块
NexusContract.Aligner/
├── Models/
│ ├── InteractionKind.cs # 交互类型枚举
│ ├── FieldMetadata.cs # 字段元数据
│ └── ContractMetadata.cs # 契约元数据
├── Parsing/
│ └── SwaggerParser.cs # OpenAPI 递归解析器
├── Generation/
│ └── CodeGenerator.cs # 代码生成引擎
├── Commands/
│ └── AlignerCommand.cs # CLI 命令定义
├── Templates/
│ └── ContractTemplate.scriban # Scriban 模板
└── Program.cs # 入口点
SwaggerParser 工作流
OpenAPI Document
↓
[远程 URL / 本地文件加载]
↓
[递归遍历 OpenApiSchema]
↓
[累积 prefix: a → a.b → a.b.c]
↓
[提取叶子节点作为 FieldMetadata]
↓
[类型映射和文档标注]
↓
List<ContractMetadata>
示例场景
场景 0:快速体验(Swagger Petstore)
适合快速上手的完整流程:
# 1. 预览:查看所有模块
nxc-align -s https://petstore.swagger.io/v2/swagger.json --list
# 2. 预览:查看 pet 模块的 8 个接口
nxc-align -s https://petstore.swagger.io/v2/swagger.json --list -m pet
# 3. 生成:仅生成 pet 模块的代码
nxc-align \
-s https://petstore.swagger.io/v2/swagger.json \
-o ./PetStore.Contracts \
-ns "Demo.PetStore.Contracts" \
-m pet
# 4. 查看生成的文件
ls -la ./PetStore.Contracts/Pet/
cat ./PetStore.Contracts/Pet/AddANewPetToTheStore.cs
生成后的代码结构:
PetStore.Contracts/
├── ContractRegistry.g.cs # 自动生成的注册表
└── Pet/
├── AddANewPetToTheStore.cs # 7 个字段
├── DeletesAPet.cs # 0 个字段(仅路径参数)
├── FindPetById.cs # 0 个字段
├── FindsPetsByStatus.cs # 0 个字段
├── FindsPetsByTags.cs # 0 个字段
├── UpdateAnExistingPet.cs # 7 个字段
├── UpdatesAPetInTheStoreWithFormData.cs # 2 个字段
└── UploadsAnImage.cs # 2 个字段
场景 1:Alipay 三方网关
nxc-align \
-s "https://opendocs.alipay.com/open-api/transaction-creation" \
-o "./Alipay.Contracts" \
-ns "MyPay.Alipay.Contracts" \
-m "Transactions"
生成文件结构:
Alipay.Contracts/
└── Transactions/
├── CreateTransactionRequest.cs
├── QueryTransactionRequest.cs
└── RefundTransactionRequest.cs
场景 2:微信支付申请
nxc-align \
-s "./wechat-applyment.json" \
-o "./WeChat.Contracts" \
-ns "MyPay.WeChat.Contracts" \
-m "Applyment"
高级用法
结合 CI/CD 流程
# .github/workflows/generate-contracts.yml
name: Generate Contracts
on:
workflow_dispatch:
push:
paths:
- 'openapi/**'
jobs:
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: '10.0.x'
- name: Generate Contracts
run: |
dotnet tool install --global NexusContract.Aligner
nxc-align -s ./openapi/main.json -o ./src/Generated -ns "MyApp.Generated"
- name: Commit changes
run: |
git config user.name "bot"
git add src/Generated/
git commit -m "chore: update generated contracts" || true
git push
与 Swagger UI 集成
生成的契约代码可直接用于 Swagger/Swashbuckle 属性标记:
[HttpPost("/api/transactions")]
[SwaggerOperation("CreateTransaction")]
public IActionResult CreateTransaction([FromBody] CreateTransactionRequest request)
{
request.Validate();
// 业务逻辑...
}
配置选项
环境变量
export NXC_ALIGN_DEFAULT_NS="MyCompany.Contracts"
export NXC_ALIGN_OUTPUT_DIR="./GeneratedContracts"
nxc-align -s https://api.example.com/swagger.json
故障排除
问题 1:返回对象为空(0 个字段)
某个接口生成的 Request 类没有任何字段
原因与解决方案:
- 这是正常现象!某些接口(如
GET /pet/{id})只有路径参数,没有请求体 - 用
--list预览可以看到每个接口的字段数:
nxc-align -s https://petstore.swagger.io/v2/swagger.json --list -m pet
# 可看到 FindPetById 字段数为 0(仅有路径参数 {petId})
# 而 AddANewPetToTheStore 字段数为 7(有请求体)
问题 2:无法加载远程 URL
error: Failed to parse OpenAPI from https://...
解决方案:
- 检查 URL 是否可访问
- 验证 HTTPS 证书(如适用)
- 使用
--debug标志查看详细错误
问题 3:本地文件找不到
error: OpenAPI file not found: ./swagger.json
解决方案:
- 确保文件路径正确
- 使用绝对路径或正确的相对路径
- 检查文件权限
问题 4:模块过滤无结果
解决方案:
- 验证 OpenAPI 中的 Tag 名称(区分大小写)
- 用
--list查看所有可用模块名
性能考虑
- 递归深度:通常限制在 10+ 层嵌套(大多数 API 不会超过 5 层)
- 处理时间:单个 OpenAPI 文档通常在 500ms 内完成
- 内存占用:约 50-100MB(取决于文档大小)
兼容性
- ✅ .NET 10(工具本身)
- ✅ .NET Standard 2.0(生成代码)
- ✅ OpenAPI 3.0 及更早版本
- ✅ Swagger 2.0 (via Microsoft.OpenApi.Readers)
扩展性
自定义模板
编辑 Templates/ContractTemplate.scriban 以自定义生成的代码:
// 添加自定义属性
[CustomAttribute("{{ operation_id }}")]
public partial class {{ class_name }}Request : IApiRequest<{{ class_name }}Response>
{
// ...自定义内容
}
自定义类型映射
修改 SwaggerParser.MapDataType() 方法以添加新的类型映射。
贡献指南
欢迎提交 Issue 和 Pull Request!请确保:
- 代码遵循项目风格指南
- 添加适当的单元测试
- 更新文档
- 提供有意义的提交消息
许可证
MIT License - 详见 LICENSE 文件
相关资源
支持
- 📧 Email: support@nexuscontract.dev
- 💬 Issues: GitHub Issues
- 📖 Wiki: 项目文档
详细文档(已合并) 🗂️
为便于使用与维护,仓库内的 Aligner 相关文档已合并到本 README。以下为来自 FINAL_SUMMARY.md、GENERATION_RULES.md、IMPLEMENTATION_SUMMARY.md、INTEGRATION.md、OPTIMIZATION_APPROACH.md 和 QUICKSTART.md 的精要汇总(保留原文要点,去除重复与冗长描述):
项目状态与目标 ✅
- 目标:将 OpenAPI/Swagger 文档自动转换为“统一用点(dot-notation)”的 C# 契约代码,生成高质量、运行期零反射的契约类。
- 目前:Aligner 已完成递归展平、模板化代码生成、ContractRegistry 输出、CLI 工具,以及性能/可维护性优化(生产就绪)。
生成规范精要(来自 GENERATION_RULES) 🔧
- Validate() 仅包含物理硬约束(NexusGuard.EnsurePhysicalAddress),留出
[AI-HINT]扩展点用于业务软约束。 - Normalize() 仅做标准化(String.Trim 等),不得写入业务状态或元数据。
- Response 类为纯 POCO,不实现接口或包含验证逻辑。
- SchemaVersion 在 Attribute 中默认为 1,生成代码不显式写出 SchemaVersion 字段。
- 生成文件组织:按 OpenAPI Tag 建目录,文件名为 OperationId 的 PascalCase + Request/Response。
核心实现概览(来自 IMPLEMENTATION_SUMMARY) ⚙️
- Models:
ContractMetadata,FieldMetadata,InteractionKind。 - Parsing:
SwaggerParser实现递归展平、类型映射(OpenAPI → C#)。 - Generation:
CodeGenerator加载 Scriban 模板渲染类文件并生成ContractRegistry.g.cs。 - CLI:
AlignerCommand(Spectre.Console.Cli)支持-s/--source,-o/--output,-ns/--namespace,-m/--module等参数。
集成与运行(来自 INTEGRATION / QUICKSTART) 🚀
- 生成后:将输出目录加入工程并调用
services.RegisterGeneratedContracts()。 - 快速命令:
nxc-align -s <OpenAPI_URL_or_file> -o ./Contracts -ns "MyApp.Contracts" -m Transactions
- CI:建议在生成后校验并提交
src/Generated,将生成步骤纳入 CI(避免手工 drift)。
优化要点(来自 OPTIMIZATION_APPROACH) ⚡
- NexusGuard.EnsurePhysicalAddress 的调用被蚀刻到 Validate():零反射、可内联、几乎无分配(对 2C2G 环境友好)。
- 通过 Expression Tree / 编译时生成实现运行期零反射;建议在 Core 启动时进行预热以消除首次请求的 JIT 抖动。
使用与调试建议
- 本地构建:
dotnet build src/NexusContract.Aligner - 运行(开发):
dotnet run -- -s <source> -o <output> -ns "DemoApp.Contracts" - 模板修改:编辑
Templates/ContractTemplate.scriban并重新运行生成。
注:原始的长文档已并入本 README,仓库中相关 Markdown 文件已替换为指向本 README 的删除说明(便于历史记录与审计)。如需查看合并前的原文,请查阅提交历史。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|