# .NET 10 平台介绍
> **文档版本**: 1.0
> **日期**: 2026-04-05
> **所属部分**: 第一部分 — 参考文档
> **单一职责**: 说明 .NET 10 平台中与本项目直接相关的特性,不涉及具体映射细节
---
## 目录
- [1. AOT 编译与单文件发布](#1-aot-编译与单文件发布)
- [2. C# 13 语言特性](#2-c-13-语言特性)
- [3. System.Text.Json 与 AOT 友好序列化](#3-systemtextjson-与-aot-友好序列化)
- [4. Microsoft.Extensions.Hosting](#4-microsoftextensionshosting)
- [5. AssemblyLoadContext 插件隔离](#5-assemblyloadcontext-插件隔离)
- [6. System.Threading.Channels 异步任务管理](#6-systemthreadingchannels-异步任务管理)
- [7. 关键 NuGet 包清单](#7-关键-nuget-包清单)
---
## 1. AOT 编译与单文件发布
### 设计意图
原始项目通过 Bun 将所有 TypeScript 打包为单一可执行二进制,做到零依赖安装。.NET 10 的 Native AOT(Ahead-of-Time)编译提供了对等的能力,并在启动速度和内存占用上更有优势。
### PublishSingleFile
`PublishSingleFile` 将运行时和应用代码打包为一个文件,发布时无需 .NET 运行时预装。
```xml
true
true
true
osx-arm64;osx-x64;linux-x64;linux-arm64;win-x64
```
### 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` 和解构支持,适合表达状态快照和配置对象。
```csharp
// 不可变配置模型
public record AppSettings(
string Model,
string Theme,
bool VerboseMode,
IReadOnlyList 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` 处理。
```csharp
// 替代 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 警告更明确。
```csharp
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]` 特性,编译器在构建时生成所有序列化代码,不依赖运行时反射。
```csharp
// 声明需要序列化的类型
[JsonSerializable(typeof(ApiRequest))]
[JsonSerializable(typeof(ApiResponse))]
[JsonSerializable(typeof(McpToolCall))]
[JsonSerializable(typeof(List))]
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` 可以零拷贝解析,不需要先将整个响应体读入内存。
```csharp
// 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 构建
```csharp
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 中运行后台循环任务的标准模式,替代原始项目中的自定义异步循环。
```csharp
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)。
### 基本用法
```csharp
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;
}
}
```
### 卸载流程
```csharp
// 加载插件
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 基本模式
```csharp
// 创建无界通道
var channel = Channel.CreateUnbounded(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);
}
```
### 有界通道与背压
```csharp
// 有界通道:满了就等待(背压)
var bounded = Channel.CreateBounded(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.* | 断言库 |