11 KiB
.NET 10 平台介绍
文档版本: 1.0
日期: 2026-04-05
所属部分: 第一部分 — 参考文档
单一职责: 说明 .NET 10 平台中与本项目直接相关的特性,不涉及具体映射细节
目录
- 1. AOT 编译与单文件发布
- 2. C# 13 语言特性
- 3. System.Text.Json 与 AOT 友好序列化
- 4. Microsoft.Extensions.Hosting
- 5. AssemblyLoadContext 插件隔离
- 6. System.Threading.Channels 异步任务管理
- 7. 关键 NuGet 包清单
1. AOT 编译与单文件发布
设计意图
原始项目通过 Bun 将所有 TypeScript 打包为单一可执行二进制,做到零依赖安装。.NET 10 的 Native AOT(Ahead-of-Time)编译提供了对等的能力,并在启动速度和内存占用上更有优势。
PublishSingleFile
PublishSingleFile 将运行时和应用代码打包为一个文件,发布时无需 .NET 运行时预装。
<!-- 项目文件中的 AOT + 单文件配置 -->
<PropertyGroup>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<AotPublish>true</AotPublish>
<RuntimeIdentifiers>osx-arm64;osx-x64;linux-x64;linux-arm64;win-x64</RuntimeIdentifiers>
</PropertyGroup>
Native AOT 的约束
AOT 编译会在发布时静态分析所有代码路径,任何运行时反射都可能被裁剪(trim)。这意味着:
System.Text.Json必须使用 Source Generator 模式,不能依赖运行时反射序列化- 插件系统无法直接 AOT,主程序集使用 AOT,插件程序集在
AssemblyLoadContext中通过 JIT 加载 - 需要为
[DynamicallyAccessedMembers]标注所有通过反射访问的类型
启动性能对比
| 方式 | 冷启动时间(参考值) |
|---|---|
| Bun 打包 JS | ~80ms |
| .NET 10 AOT | ~15-30ms |
| .NET 10 JIT(无 AOT) | ~150-300ms |
2. C# 13 语言特性
设计意图
TypeScript 的类型系统依赖接口、联合类型和 Zod 运行时校验。C# 13 提供了更强的编译时保证,用 record 类型替代不可变 DTO,用模式匹配替代联合类型的分支处理。
Record 类型
Record 类型天然不可变,自动生成 Equals、GetHashCode、ToString 和解构支持,适合表达状态快照和配置对象。
// 不可变配置模型
public record AppSettings(
string Model,
string Theme,
bool VerboseMode,
IReadOnlyList<string> AllowedDirectories
);
// 带 required 修饰符的 init-only 属性
public record FileReadInput
{
public required string FilePath { get; init; }
public int? Offset { get; init; }
public int? Limit { get; init; }
}
模式匹配
C# 13 的模式匹配可以替代 TypeScript 中对联合类型的 switch + instanceof 处理。
// 替代 TS 的 if (msg.type === 'tool_use') { ... }
var result = message switch
{
ToolUseMessage toolUse => HandleToolUse(toolUse),
AssistantMessage assistant => HandleAssistant(assistant),
ErrorMessage { Code: >= 500 } serverError => HandleServerError(serverError),
_ => HandleUnknown(message)
};
required init 属性
required 关键字在编译时强制调用方必须初始化某个属性,比构造函数参数更灵活,比 Nullable 警告更明确。
public class ToolExecutionContext
{
public required string SessionId { get; init; }
public required IPermissionEngine PermissionEngine { get; init; }
public CancellationToken CancellationToken { get; init; }
}
3. System.Text.Json 与 AOT 友好序列化
设计意图
原始项目直接使用 JSON.parse/JSON.stringify,无类型安全。System.Text.Json 提供高性能序列化,配合 Source Generator 完全绕过运行时反射,AOT 环境下也可正常工作。
Source Generator 模式
通过 [JsonSerializable] 特性,编译器在构建时生成所有序列化代码,不依赖运行时反射。
// 声明需要序列化的类型
[JsonSerializable(typeof(ApiRequest))]
[JsonSerializable(typeof(ApiResponse))]
[JsonSerializable(typeof(McpToolCall))]
[JsonSerializable(typeof(List<ToolDefinition>))]
internal partial class AppJsonContext : JsonSerializerContext { }
// 使用时传入 context
var json = JsonSerializer.Serialize(request, AppJsonContext.Default.ApiRequest);
var response = JsonSerializer.Deserialize(json, AppJsonContext.Default.ApiResponse);
流式 JSON 处理
MCP 和 API 响应都基于流式 JSON,使用 Utf8JsonReader 可以零拷贝解析,不需要先将整个响应体读入内存。
// SSE 流式解析示例
await foreach (var line in sseReader.ReadLinesAsync(ct))
{
if (!line.StartsWith("data: ")) continue;
var data = line["data: ".Length..];
if (data == "[DONE]") break;
var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(data));
var chunk = JsonSerializer.Deserialize(ref reader, AppJsonContext.Default.StreamChunk);
yield return chunk;
}
4. Microsoft.Extensions.Hosting
设计意图
原始项目没有显式的 DI 容器,各模块通过模块级变量和闭包共享状态。.NET 的 Microsoft.Extensions.Hosting 提供了标准化的应用生命周期管理,包括 DI 注册、配置系统和 BackgroundService。
Host 构建
var host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((ctx, cfg) =>
{
cfg.AddJsonFile("appsettings.json", optional: true);
cfg.AddEnvironmentVariables("FREECODE_");
cfg.AddCommandLine(args);
})
.ConfigureServices((ctx, services) =>
{
services.AddCoreServices()
.AddEngine()
.AddTools()
.AddCommands()
.AddApiProviders()
.AddMcp()
.AddLsp();
})
.ConfigureLogging(logging =>
{
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Warning); // 终端应用默认不打印 Info 日志
})
.Build();
BackgroundService
BackgroundService 是 .NET 中运行后台循环任务的标准模式,替代原始项目中的自定义异步循环。
public class TaskSchedulerService : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await foreach (var task in _taskChannel.Reader.ReadAllAsync(stoppingToken))
{
_ = Task.Run(() => ExecuteTaskAsync(task, stoppingToken), stoppingToken);
}
}
}
5. AssemblyLoadContext 插件隔离
设计意图
原始项目使用 动态 import() 加载插件,JavaScript 的模块系统天然支持按需加载。.NET 中通过 AssemblyLoadContext 实现对等的运行时程序集隔离,并支持卸载(collectible context)。
基本用法
public class PluginLoadContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver _resolver;
public PluginLoadContext(string pluginPath)
: base(isCollectible: true) // 可卸载
{
_resolver = new AssemblyDependencyResolver(pluginPath);
}
protected override Assembly? Load(AssemblyName assemblyName)
{
// 优先从插件目录解析,避免与主程序集冲突
var assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
return assemblyPath != null ? LoadFromAssemblyPath(assemblyPath) : null;
}
}
卸载流程
// 加载插件
var context = new PluginLoadContext(pluginPath);
var assembly = context.LoadFromAssemblyPath(pluginPath);
var plugin = (IPlugin)Activator.CreateInstance(assembly.GetType("MyPlugin")!)!;
// 卸载插件(释放所有强引用后 GC 自动回收)
context.Unload();
AOT 注意事项
主程序集使用 AOT 编译,但插件程序集在运行时通过 AssemblyLoadContext 以 JIT 模式加载。这是混合部署模式:主入口 AOT 启动快、内存小,插件保持 JIT 的灵活性。
6. System.Threading.Channels 异步任务管理
设计意图
原始项目的后台任务通过自定义队列和 Promise 链管理,存在竞态风险。System.Threading.Channels 是 .NET 内建的高性能生产者-消费者通道,线程安全,背压(backpressure)支持完善。
Channel 基本模式
// 创建无界通道
var channel = Channel.CreateUnbounded<BackgroundTask>(new UnboundedChannelOptions
{
SingleWriter = false,
SingleReader = true // 单消费者简化并发模型
});
// 生产者(任意线程)
await channel.Writer.WriteAsync(new LocalShellTask { Command = "npm test" }, ct);
// 消费者(BackgroundService 中)
await foreach (var task in channel.Reader.ReadAllAsync(ct))
{
await ProcessTaskAsync(task, ct);
}
有界通道与背压
// 有界通道:满了就等待(背压)
var bounded = Channel.CreateBounded<ApiRequest>(new BoundedChannelOptions(capacity: 100)
{
FullMode = BoundedChannelFullMode.Wait
});
7. 关键 NuGet 包清单
以下是本项目直接依赖的 NuGet 包,版本号为设计时目标版本。
| 包名 | 版本 | 用途 |
|---|---|---|
Terminal.Gui |
2.* | 终端 TUI 框架,替代 React+Ink |
Spectre.Console |
0.* | 富文本输出:表格、进度条、面板 |
System.CommandLine |
2.* | CLI 参数解析,替代 Commander.js |
FluentValidation |
12.* | POCO 对象校验,替代 Zod |
JsonSchema.Net |
7.* | JSON Schema 生成与校验 |
Refit |
8.* | 强类型 HTTP 客户端 |
Polly |
8.* | 重试、熔断、超时策略 |
StreamJsonRpc |
2.* | JSON-RPC 2.0 实现,用于 MCP 协议 |
OmniSharp.Extensions.LanguageServer.Client |
0.* | LSP 客户端 |
Grpc.Net.Client |
2.* | gRPC 客户端(部分 API 提供商) |
Microsoft.Identity.Client (MSAL) |
4.* | OAuth/OIDC 认证 |
IdentityModel.OidcClient |
6.* | OIDC 客户端流程 |
AWSSDK.BedrockRuntime |
4.* | AWS Bedrock 流式 API |
Google.Apis.Auth |
1.* | Google Cloud 认证(Vertex AI) |
Microsoft.AspNetCore.SignalR.Client |
10.* | WebSocket 高层抽象 |
Markdig |
0.* | Markdown 渲染 |
DiffPlex |
1.* | diff 计算与展示 |
SixLabors.ImageSharp |
3.* | 图片处理 |
PdfPig |
0.* | PDF 文本提取 |
YamlDotNet |
16.* | YAML 解析 |
Microsoft.Extensions.Hosting |
10.* | DI + 生命周期管理 |
System.Threading.Channels |
10.* | 生产者-消费者通道 |
xunit |
2.* | 单元测试框架 |
NSubstitute |
5.* | Mock 框架 |
FluentAssertions |
7.* | 断言库 |