C# TypeSpec生成代码方法 C#如何使用TypeSpec定义API并生成代码

来源:这里教程网 时间:2026-02-21 17:41:16 作者:

TypeSpec 是什么,和 C# 有什么关系?

TypeSpec 本身不是 C# 的一部分,它是微软推出的、基于 TypeScript 的接口定义语言(IDL),用来描述 API(尤其是 RESTful 服务)的结构。它不直接生成 C# 类型,但可通过插件(如

@typespec/openapi3
+
@typespec/csharp
)输出 C# 客户端或服务端代码。关键点是:TypeSpec 不编译进运行时,它只在设计/生成阶段起作用。

如果你期望“写个 .tsp 文件就自动编译成可运行的 C# 项目”,那会失望——它更像 Swagger + TypeScript 的增强版,目标是统一契约、驱动多语言代码生成。

如何用 TypeSpec 定义一个简单 API 并生成 C# 客户端?

先确保安装了 Node.js 和 TypeSpec CLI:

npm install -g @typespec/cli

创建

main.tsp
,定义一个待生成的 API:

import "@typespec/http";
import "@typespec/openapi3";
import "@typespec/csharp";
<p>@service({title: "TodoService"})
namespace TodoApi {
@route("/todos")
@get
op listTodos(): Todo[];</p><p>@route("/todos/{id}")
@get
op getTodo(@path id: string): Todo;
}</p><p>model Todo {
@key id: string;
name: string;
completed: boolean;
}

然后执行生成命令(需先安装

@typespec/csharp
插件):

npx tsp compile . --emit @typespec/csharp --option "@typespec/csharp.emitter-output-dir=./GeneratedClient"

生成的 C# 代码默认包含

TodoApiClient
Todo
模型等,使用的是
System.Net.Http
System.Text.Json
,不依赖第三方 HTTP 客户端库。

@typespec/csharp
目前仍为预览版,生成的代码可能缺少部分特性(如分页支持、自定义序列化器钩子)
必须显式导入
@typespec/csharp
,否则
--emit
会静默失败
路径参数(
@path
)、查询参数(
@query
)、请求体(
@body
)需正确标注,否则生成的 C# 方法签名可能漏参数或类型错误

C# 服务端生成是否可行?

目前(2024 年中)

@typespec/csharp
官方仅支持客户端生成(即调用方代码),不生成 ASP.NET Core Controller 或 Minimal API。想用 TypeSpec 驱动服务端,有两条现实路径:

@typespec/openapi3
导出 OpenAPI JSON,再用
NSwag
Microsoft.dotnet-openapi
工具反向生成服务端骨架(但会丢失 TypeSpec 特有语义,如
@visibility
@friendlyName
手动实现 Controller,并用
[ProducesResponseType]
等特性对齐 OpenAPI 输出,再通过
tsp compile . --emit @typespec/openapi3
验证一致性
社区有实验性插件(如
typespec-csharp-server
)尝试生成 Minimal API,但稳定性差、无官方维护,不建议用于生产

换句话说:TypeSpec 当前对 C# 服务端是“契约先行但手写实现”,而非“契约即实现”。

常见报错与绕过方式

运行

tsp compile
时容易遇到以下问题:

Error: Cannot resolve emitter "@typespec/csharp"
→ 检查是否在项目根目录执行,且
package.json
中已声明
@typespec/csharp
为 devDependency;不要用全局
npx tsp
调用本地插件
生成的 C# 类名含非法字符(如
My-Resource
)→ TypeSpec 默认转为 PascalCase,但连字符会被忽略导致冲突(
MyResource
MyResource
),改用
@friendlyName("MyResource")
显式指定
DateTime 字段生成为
DateTimeOffset?
而非
DateTime?
→ 这是 OpenAPI 3.0 对时间字段的规范行为,若后端强制用
DateTime
,需在 C# 客户端手动映射或改用
@type
注解配合自定义序列化器

最易被忽略的一点:TypeSpec 的

@doc
@summary
等注释默认不会出现在生成的 C# XML 注释里,需额外配置
--option "@typespec/csharp.include-docs=true"
才启用。

相关推荐