# .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.* | 断言库 |