完善项目描述及新增协作开发指令文档 本次提交: - 优化 MapApi、NewLife.Map、Test、XUnitTest 项目描述和标题,使其更准确反映功能定位和用途。 - 新增四份协作与开发指令文档:benchmark.instructions.md(性能测试规范)、development.instructions.md(AI辅助开发流程)、net.instructions.md(网络编程规范)、xcode.instructions.md(XCode数据建模与实体操作指南)。 - 统一和提升团队协作、编码、文档产出规范,为多成员/AI协同开发提供权威参考,增强项目可维护性与开发效率。智能大石头 authored at 2026-03-04 22:08:39
diff --git a/.github/instructions/benchmark.instructions.md b/.github/instructions/benchmark.instructions.md
new file mode 100644
index 0000000..56ffc19
--- /dev/null
+++ b/.github/instructions/benchmark.instructions.md
@@ -0,0 +1,77 @@
+---
+applyTo: "**/Benchmark/**"
+---
+
+# 性能测试指令
+
+适用于性能测试、压力测试、基准测试、BenchmarkDotNet 相关任务。
+
+---
+
+## 1. 项目结构
+
+- 基准测试统一放在 `Benchmark/` 项目,按主题分子目录(如 `PacketBenchmarks/`、`CacheBenchmarks/`)
+- 入口 `Program.cs` 使用 `BenchmarkSwitcher` 模式,**不要修改**
+- TFM 使用最新稳定版,`<LangVersion>latest</LangVersion>`
+
+## 2. 代码规范
+
+遵循主指令全部编码规范(类型名用 `String`/`Int32` 等、file-scoped namespace),另有以下补充:
+
+- **命名空间**:`Benchmark.{主题}Benchmarks`
+- **类名**:`{被测类型}Benchmark` 或 `{被测主题}Benchmark`
+- **必须标注** `[MemoryDiagnoser]` 和 `[SimpleJob]`(需调整迭代次数时用 `[SimpleJob(iterationCount: N)]`)
+- **方法描述**:`[Benchmark(Description = "中文描述")]`,方便报告阅读
+- **参数化**:用 `[Params]` 或 `[ParamsSource]` 控制数据规模
+- **初始化 / 清理**:分别放 `[GlobalSetup]` 和 `[GlobalCleanup]`
+- **分组**:同类测试用 `#region` 分组
+- **多线程并发**:动态线程数包含 CPU 核心数,推荐模板:
+
+```csharp
+public static IEnumerable<Int32> ThreadCounts
+{
+ get
+ {
+ var cores = Environment.ProcessorCount;
+ var set = new SortedSet<Int32> { 1, 4, 8, 32 };
+ set.Add(cores);
+ return set;
+ }
+}
+
+[ParamsSource(nameof(ThreadCounts))]
+public Int32 ThreadCount { get; set; }
+```
+
+## 3. 运行要求
+
+- 必须以 **Release 模式**运行,获取有代表性的峰值数据
+- 运行全部:`dotnet run -c Release`
+- 运行指定类:`dotnet run -c Release -- --filter *ClassName*`
+- ❌ 禁止在 Debug 模式下采集数据写入报告
+
+## 4. 测试维度
+
+- **并发维度**:单线程 + 多线程(多线程含与当前 CPU 核心数相同的并发数)
+- **操作维度**:单一操作 + 批量操作
+
+## 5. 常见错误
+
+- ❌ 在 `[Benchmark]` 方法内做初始化(应放 `[GlobalSetup]`)
+- ❌ 忽略返回值导致 JIT 死码消除(确保返回或赋值给字段)
+- ❌ 手动 `Stopwatch` 计时(BDN 自动处理)
+- ❌ `using` 的 `Dispose` 开销混入测量(仅在测试 Dispose 本身时才包含)
+
+## 6. 报告存放
+
+`Doc/Benchmark/{测试主题}性能测试.md`(UTF-8 无 BOM)
+
+## 7. 报告结构(顺序固定)
+
+1. **性能概览**(放最前:一句话点明被测功能用途 + 简单语言总结核心发现)
+2. 测试环境 → 测试方法 → 测试结果(BDN 原始表格,保留 Mean/Error/StdDev/Allocated)
+3. 核心指标(换算 msg/s、QPS 等业务指标)
+4. **对比分析**
+ - 纵向:同场景不同并发趋势,找出最优并发点
+ - 横向:不同方案同并发差异百分比
+5. 性能瓶颈定位 → 优化建议(按优先级排序,含预期收益)
diff --git a/.github/instructions/development.instructions.md b/.github/instructions/development.instructions.md
new file mode 100644
index 0000000..44729b4
--- /dev/null
+++ b/.github/instructions/development.instructions.md
@@ -0,0 +1,324 @@
+---
+applyTo: "Doc/**"
+---
+
+# AI 辅助开发流程指令
+
+适用于新建应用系统、新增功能模块、需求整理、架构设计等研发全流程任务。
+
+---
+
+## 1. 流程总览
+
+```
+需求整理 → 需求评审与拆分 → 技术方案设计 → 任务分解 → 迭代开发 → 集成验证 → 验收回顾
+```
+
+**核心原则**:大需求必须拆小,每个迭代交付可验证的最小功能单元。禁止"一次性全做完"。
+
+---
+
+## 2. 各阶段规范
+
+### 2.1 需求整理
+
+用户提供原始描述(口语化、列表、草稿均可),AI 整理为以下结构(需求 + 功能清单 + 验收 合为一个文件):
+
+```markdown
+# {项目/模块名}需求
+
+## 1. 背景与目标
+- 为什么做(痛点/动机)
+- 做到什么程度算成功(可衡量目标)
+
+## 2. 用户角色
+| 角色 | 说明 | 核心诉求 |
+|------|------|---------|
+
+## 3. 功能需求
+### 3.1 {功能模块名}
+- **描述**:一句话说明
+- **用户故事**:作为{角色},我希望{操作},以便{价值}
+- **验收条件**(AC):
+ - [ ] 条件 1
+ - [ ] 条件 2
+- **优先级**:Must / Should / Could / Won't
+
+## 4. 非功能需求
+- 性能 / 安全 / 兼容性(三项必填)
+
+## 5. 边界与约束
+- 不做什么(明确排除项)
+- 已知限制 / 技术债务
+
+## 6. 功能清单与迭代计划
+(需求评审拆分后填写,见 2.2)
+
+## 7. 验收记录
+(开发完成后填写,见 2.7)
+
+## 8. 术语表
+| 术语 | 定义 |
+|------|------|
+```
+
+**规则**:每个功能必须有 AC,无 AC 不可进入开发;优先级用 MoSCoW 四级;非功能需求至少覆盖性能、安全、兼容性。
+
+### 2.2 需求评审与拆分
+
+按**纵向切片**(端到端功能,非技术层)拆分,遵循 INVEST 原则,单个功能单元 ≤ 1-2 天工作量,有依赖须标注。
+
+写入需求文档「6. 功能清单与迭代计划」:
+
+```markdown
+## 6. 功能清单与迭代计划
+
+### 迭代 1:{主题}(Must 级别)
+| 编号 | 功能点 | 验收条件 | 前置依赖 | 预估工作量 |
+|------|--------|---------|---------|----------|
+| F001 | xxx | AC1, AC2 | 无 | 0.5d |
+| F002 | xxx | AC1 | F001 | 1d |
+
+### 迭代 2:{主题}(Should 级别)
+...
+```
+
+### 2.3 技术方案设计
+
+```markdown
+# {项目/模块名}架构
+
+## 1. 架构概览
+## 2. 数据模型
+## 3. 接口设计
+| 接口 | 方法 | 路径/签名 | 入参 | 出参 | 说明 |
+|------|------|----------|------|------|------|
+## 4. 技术选型
+| 领域 | 选型 | 理由 |
+|------|------|------|
+## 5. 关键设计决策
+| 决策点 | 方案 | 备选方案 | 选择理由 |
+|--------|------|---------|---------|
+## 6. 任务分解
+(见 2.4)
+## 7. 风险与缓解
+| 风险 | 影响 | 缓解措施 |
+|------|------|---------|
+```
+
+**规则**:优先使用 NewLife 已有组件(XCode、Remoting、Stardust 等);数据模型考虑 XCode 实体规范;接口遵循现有 API 风格。
+
+### 2.4 任务分解
+
+单个任务 = 一次 AI 对话可完成的工作量(编码 + 测试 + 自测通过)。写入技术方案「6. 任务分解」:
+
+```markdown
+### 任务 T001:{动词 + 目标}
+- **对应功能**:F001
+- **输入**:前置条件 / 已有代码
+- **产出**:新增/修改哪些文件
+- **验收**:怎样算完成
+```
+
+**批次编排**(用于自治模式,见第 6 节):按依赖关系编排为批次,每批次 5-8 个任务,同批次内尽量无相互依赖,基础设施任务排在前面,每批次结束设 `[检查点 N]`,标注本批次产出是下批次哪些输入。
+
+### 2.5 迭代开发
+
+流程:`理解任务 → 检索现有实现 → 编码 → 编译通过 → 测试通过 → 提交说明`
+
+- 严格遵守主指令编码规范,每个任务必须编译通过
+- 常规模式:遇歧义暂停确认;自治模式:记录跳过继续(见第 6 节)
+- 有依赖按顺序执行,不跳跃
+
+### 2.6 集成验证
+
+全部编译通过 → 单元测试通过 → 端到端主流程走通 → 异常场景覆盖 → 性能符合预期
+
+### 2.7 验收与回顾
+
+对照需求文档逐条验收,写入「7. 验收记录」:
+
+```markdown
+## 7. 验收记录
+
+### 功能验收
+| 编号 | 功能点 | 验收条件 | 状态 | 备注 |
+|------|--------|---------|------|------|
+
+### 遗留问题
+| 问题 | 影响 | 后续计划 |
+|------|------|---------|
+
+### 经验总结
+- 做得好的 / 待改进的
+```
+
+---
+
+## 3. 文档存放规范
+
+全流程仅产出 **2 个文档**,扁平存放在 `Doc/` 下:
+
+| 文档 | 文件名 | 包含内容 |
+|------|--------|--------|
+| 需求文档 | `Doc/{项目名}需求.md` | 背景目标 + 功能需求 + 功能清单 + 验收记录 + 术语表 |
+| 技术方案 | `Doc/{项目名}架构.md` | 架构 + 数据模型 + 接口 + 技术选型 + 任务分解 + 风险 |
+
+UTF-8 无 BOM;已有文件必须先读取再增量修改,禁止覆盖;各阶段产出追加到对应章节,不新建文件。
+
+---
+
+## 4. AI 协作要点
+
+### 4.1 阶段切换
+
+| 用户说 | 进入阶段 |
+|--------|---------|
+| "整理需求"/"写需求" | 2.1 需求整理 |
+| "拆分"/"拆解"/"排优先级" | 2.2 需求评审与拆分 |
+| "技术方案"/"架构设计"/"怎么实现" | 2.3 技术方案设计 |
+| "开始开发"/"写代码"/"实现 F001" | 2.5 迭代开发 |
+| "全部搞完"/"批量开发"/"自治模式"/"一次性做完"/"继续处理"/"接着做" | 第 6 节自治批处理 |
+| "验收"/"检查完成情况" | 2.7 验收与回顾 |
+| 一大段描述未指定阶段 | 默认 2.1 需求整理 |
+
+### 4.2 主动引导
+
+每阶段完成后提示下一步:需求整理完 → 拆分? → 技术方案? → 任务分解 → 开发?
+
+### 4.3 大需求防护
+
+功能点 > 5 / 实体 > 3 / 跨 2 层以上 / 描述 > 500 字 → 必须先拆分再开发。
+
+---
+
+## 5. 常见反模式(禁止)
+
+- ❌ 跳过需求直接编码
+- ❌ 一次性输出所有代码(大需求必须拆迭代或使用自治模式)
+- ❌ 需求文档没有验收条件
+- ❌ 功能拆分按技术层而非用户价值
+- ❌ 任务没有完成标准就开始编码
+- ❌ 完成后不做验收对照
+- ❌ 自治模式下遇阻塞问题死等用户(应记录跳过,继续后续)
+- ❌ 自治模式下做需要人工决策的架构变更(应记录待确认,现有方案兜底)
+- ❌ 跨批次不做编译验证
+
+---
+
+## 6. 自治批处理模式
+
+架构师已确认需求和技术方案后,AI 按任务清单自主执行,最小化人工介入。
+
+### 6.1 进入条件(全部满足)
+
+- [ ] 需求文档已完成且架构师已确认
+- [ ] 技术方案已完成且架构师已确认
+- [ ] 任务已分解并编排为批次
+- [ ] 用户明确触发("全部搞完"/"批量开发"/"自治模式"等)
+
+未满足时提示缺少哪些条件。
+
+### 6.2 计划结构与循环刷新
+
+AI 用 plan 工具创建层次化计划,「前置刷新 + 批次执行」循环:
+
+```
+1. [前置] 读取需求文档与技术方案
+2. [前置] 读取任务清单与进度状态
+3. [前置] 全量编译确认基线
+4. [前置] 识别可并行的批次组
+5. [批次1] 执行 T001-T005(子步骤展开各任务)
+6. [检查点1] 输出批次1报告
+7. [刷新] 重读需求文档与技术方案
+8. [批次2] 执行 T006-T010
+9. [检查点2] 输出批次2报告
+...(循环:刷新 → 批次 → 检查点)
+N-2. [后置] 全量编译与集成验证
+N-1. [后置] 补完被跳过的任务
+N. [后置] 生成验收报告
+```
+
+**要点**:
+- 主步骤 15-25 个(不超过 30),子步骤展开具体任务仅供参考不单独追踪
+- 刷新步骤穿插在每两个批次之间,`get_file` 重读文档对抗上下文漂移
+- 用 `update_plan_progress` 跟踪主步骤,不为每个子任务调用
+- 无依赖的批次可合并为一个主步骤执行,有依赖的必须顺序执行
+
+### 6.3 执行协议
+
+| 情况 | 处理方式 |
+|------|----------|
+| 任务明确无歧义 | 直接执行:编码 → 编译 → 测试 |
+| 小歧义可合理推断 | 执行并在问题日志记录推断依据 |
+| 重大歧义或多种等价方案 | 标记 `⏸️ 待确认`,跳过 |
+| 前置任务被跳过 | 标记 `⏸️ 依赖阻塞:T0xx`,跳过 |
+| 编译失败短时间无法修复 | 回滚改动,记录并跳过 |
+| 涉及公共 API / 架构变更 | 标记 `⏸️ 需架构师决策`,兜底或跳过 |
+
+### 6.4 检查点报告
+
+每批次完毕后输出:
+
+```markdown
+## 检查点 N 报告
+
+### 完成情况
+| 任务 | 状态 | 说明 |
+|------|------|------|
+| T001 | ✅ 完成 | |
+| T003 | ⏸️ 跳过 | 需确认:xxx |
+
+### 编译状态
+- 全量编译:✅ 通过 / ❌ 失败(错误详情)
+
+### 问题日志
+| 编号 | 类型 | 描述 | 影响任务 | 建议方案 |
+|------|------|------|---------|----------|
+
+### 统计
+- 本批次 N 个,完成 X 个,跳过 Y 个
+- 累计进度:已完成 X / 总计 Z(XX%)
+- 上下文预估:{已处理任务数} / {建议上限}
+```
+
+### 6.5 用户回复与继续
+
+架构师回来后:AI 呈现检查点报告 → 架构师批量回复问题("Q001 OK,Q002 选 A")→ AI 修正推断 + 执行跳过的任务 + 继续下批次 → 循环至完成。
+
+触发词:"继续"/"继续处理"/"回复完了"/"接着做"
+
+### 6.6 质量护栏(自动执行)
+
+编译门禁(失败即修复或回滚)/ 命名与技术方案一致 / 编码规范严格遵守 / 新增代码前搜索现有实现避免重复 / 不擅自引入新 NuGet 包
+
+### 6.7 会话边界处理
+
+每个检查点后、连续完成 15+ 任务后、搜索结果不准确时 → 评估是否需要新会话。
+
+**新会话续接模板**:
+
+```
+我们在做 {项目名} 的自治批处理开发。
+- 需求文档:Doc/{项目名}需求.md
+- 技术方案:Doc/{项目名}架构.md
+- 当前进度:批次 N 已完成,从批次 N+1 的 T0xx 开始继续
+- 待解决问题:{问题编号}
+请读取以上文档,从 T0xx 继续执行,自治模式。
+```
+
+上下文即将耗尽时 AI 主动提醒并生成上述模板。新会话前 4 步仍为前置刷新,已完成批次直接标记完成。
+
+### 6.8 批次大小建议
+
+| 复杂度 | 批次大小 |
+|--------|---------|
+| 简单(CRUD) | 8-10 |
+| 中等(业务逻辑) | 5-7 |
+| 复杂(算法、并发) | 3-5 |
+
+单会话上限:3-4 个批次(约 15-25 个任务)。
+
+---
+
+(完)
diff --git a/.github/instructions/net.instructions.md b/.github/instructions/net.instructions.md
new file mode 100644
index 0000000..ba7509b
--- /dev/null
+++ b/.github/instructions/net.instructions.md
@@ -0,0 +1,573 @@
+---
+applyTo: "**/Net/**"
+---
+
+# 网络编程指令
+
+适用于基于 `NewLife.Net` 的网络服务器(`NetServer`)和客户端(`ISocketClient`)开发任务。
+
+---
+
+## 1. 架构概览
+
+NewLife 网络框架分为两层:
+
+| 层级 | 服务端 | 客户端 | 说明 |
+|------|--------|--------|------|
+| **应用层** | `NetServer` / `NetServer<TSession>` | — | 管理监听、会话生命周期、管道 |
+| **传输层** | `TcpServer` / `UdpServer` | `TcpSession` / `UdpServer`(客户端模式) | 底层 Socket 收发 |
+| **会话** | `NetSession` / `NetSession<TServer>` | — | 每个连接对应一个会话,业务逻辑入口 |
+| **管道** | `IPipeline` + `IPipelineHandler` | 同左 | 编解码、粘包拆包、消息匹配 |
+
+**关键接口**:
+- `ISocketClient` — 客户端连接接口(Open/Close/Send/Receive)
+- `ISocketRemote` — 远程通信接口(Send/Receive/SendMessageAsync)
+- `INetSession` — 网络会话接口(服务端每个连接的业务处理单元)
+- `INetHandler` — 网络数据处理器接口(Init/Process)
+
+---
+
+## 2. 服务端开发规范
+
+### 2.1 基本模式
+
+推荐使用泛型 `NetServer<TSession>` + 自定义 `NetSession` 子类:
+
+```csharp
+/// <summary>自定义网络服务器</summary>
+class MyServer : NetServer<MySession> { }
+
+/// <summary>自定义会话,每个客户端连接对应一个实例</summary>
+class MySession : NetSession<MyServer>
+{
+ /// <summary>客户端连接</summary>
+ protected override void OnConnected()
+ {
+ base.OnConnected();
+ WriteLog("客户端已连接 {0}", Remote);
+ }
+
+ /// <summary>收到客户端数据</summary>
+ protected override void OnReceive(ReceivedEventArgs e)
+ {
+ base.OnReceive(e);
+ // 业务处理
+ }
+
+ /// <summary>客户端断开</summary>
+ protected override void OnDisconnected(String reason)
+ {
+ base.OnDisconnected(reason);
+ }
+}
+```
+
+### 2.2 服务器启动配置
+
+```csharp
+var server = new MyServer
+{
+ Port = 8080, // 监听端口,0 表示随机
+ ProtocolType = NetType.Tcp, // Tcp/Udp/Unknown(同时监听)
+ // AddressFamily = AddressFamily.InterNetwork, // 仅IPv4,默认同时IPv4+IPv6
+ ServiceProvider = provider, // 依赖注入
+ Log = XTrace.Log, // 应用日志
+ SessionLog = XTrace.Log, // 会话日志
+ Tracer = tracer, // APM 追踪
+#if DEBUG
+ SocketLog = XTrace.Log, // Socket 层日志(仅调试)
+ LogSend = true,
+ LogReceive = true,
+#endif
+};
+server.Start();
+```
+
+### 2.3 会话生命周期
+
+```
+连接建立 → OnConnected() → OnReceive()... → OnDisconnected(reason) → Dispose()
+```
+
+- **OnConnected**:初始化会话状态、发送欢迎消息
+- **OnReceive**:核心业务处理入口,`e.Packet` 为原始数据,`e.Message` 为管道解码后的消息
+- **OnDisconnected**:清理资源、记录日志,`reason` 包含断开原因
+- 会话内可通过 `ServiceProvider` 获取 Scoped 服务
+
+### 2.4 服务端发送数据
+
+| 方法 | 说明 |
+|------|------|
+| `Send(IPacket)` | 直接发送原始数据,不经过管道 |
+| `Send(String)` | 发送字符串,默认 UTF-8 |
+| `Send(ReadOnlySpan<Byte>)` | 高性能发送 |
+| `SendMessage(Object)` | 通过管道编码后发送,不等待响应 |
+| `SendReply(Object, ReceivedEventArgs)` | 发送响应消息,与请求关联(用于 StandardCodec 等协议) |
+| `SendMessageAsync(Object)` | 通过管道发送并等待响应 |
+
+### 2.5 群发
+
+```csharp
+// 群发数据给所有在线客户端
+await server.SendAllAsync(data);
+
+// 带过滤条件群发
+await server.SendAllAsync(data, session => session.ID > 100);
+
+// 群发管道消息
+server.SendAllMessage(message, session => session["VIP"] is true);
+```
+
+群发要求 `UseSession = true`(默认开启)。
+
+### 2.6 事件模式(简单场景)
+
+不需要自定义会话时,可直接使用事件:
+
+```csharp
+var server = new NetServer { Port = 8080 };
+server.Received += (sender, e) =>
+{
+ if (sender is INetSession session)
+ session.Send(e.Packet); // Echo
+};
+server.Start();
+```
+
+---
+
+## 3. 客户端开发规范
+
+### 3.1 创建客户端
+
+通过 `NetUri.CreateRemote()` 扩展方法创建:
+
+```csharp
+// TCP 客户端
+var client = new NetUri("tcp://127.0.0.1:8080").CreateRemote();
+
+// UDP 客户端
+var client = new NetUri("udp://127.0.0.1:8080").CreateRemote();
+
+// WebSocket 客户端
+var client = new NetUri("ws://127.0.0.1:8080/path").CreateRemote();
+```
+
+`CreateRemote` 根据协议自动返回 `TcpSession` / `UdpServer` / `WebSocketClient`。
+
+### 3.2 客户端使用
+
+```csharp
+var uri = new NetUri("tcp://127.0.0.1:8080");
+var client = uri.CreateRemote();
+client.Log = XTrace.Log;
+client.Open();
+
+// 发送原始数据(不经过管道)
+client.Send("Hello");
+
+// 事件驱动接收
+client.Received += (sender, e) =>
+{
+ // e.Packet 原始数据,e.Message 管道解码后的消息
+};
+
+// 或同步/异步接收
+using var pk = client.Receive();
+using var pk = await client.ReceiveAsync(cancellationToken);
+
+client.Close("完成"); // 或 client.Dispose()
+```
+
+### 3.3 请求-响应模式(需要管道编解码器)
+
+```csharp
+var client = new NetUri("tcp://127.0.0.1:8080").CreateRemote();
+client.Add<StandardCodec>();
+client.Open();
+
+var response = await client.SendMessageAsync(payload, cancellationToken); // 等待响应
+client.SendMessage(message); // 不等待响应
+```
+
+### 3.4 SSL/TLS
+
+```csharp
+// 服务端 SSL
+var server = new NetServer
+{
+ Port = 443,
+ SslProtocol = SslProtocols.Tls12,
+ Certificate = new X509Certificate2("server.pfx", "password"),
+};
+
+// 客户端 SSL(自动根据端口判断,或手动指定)
+var client = new NetUri("tcp://host:443").CreateRemote();
+if (client is TcpSession tcp)
+{
+ tcp.SslProtocol = SslProtocols.Tls12;
+ // tcp.Certificate = cert; // 客户端证书(如果服务端要求)
+}
+```
+
+---
+
+## 4. 管道与编解码器
+
+### 4.1 管道机制
+
+管道(`IPipeline`)是处理器链,Read/Write 返回值作为下一个处理器的输入,返回 `null` 截断管道:
+
+```
+接收:Socket → [Codec1.Read] → [Codec2.Read] → FireRead → OnReceive
+发送:SendMessage → [Codec2.Write] → [Codec1.Write] → FireWrite → Socket
+```
+
+Open 正序传播,Close 逆序传播。先添加的在底层(靠近 Socket),后添加的在上层(靠近业务)。
+
+### 4.2 内置编解码器
+
+| 编解码器 | 基类 | 说明 | 典型场景 |
+|---------|------|------|---------|
+| `StandardCodec` | `MessageCodec<IMessage>` | 4字节头部(Flag+Seq+Length),支持请求-响应匹配 | 自定义 RPC 协议 |
+| `LengthFieldCodec` | `MessageCodec<IPacket>` | 长度字段头部,可配置偏移和大小 | MQTT、通用二进制协议 |
+| `JsonCodec` | `Handler` | JSON 文本编解码,不处理粘包 | 文本协议(通常与 StandardCodec 级联) |
+| `SplitDataCodec` | `Handler` | 分隔符拆包(默认 `\r\n`) | 文本行协议 |
+| `WebSocketCodec` | `Handler` | WebSocket 帧编解码 | WebSocket 通信 |
+
+### 4.3 添加编解码器
+
+```csharp
+// 服务端添加
+server.Add<StandardCodec>();
+
+// 客户端添加
+client.Add<StandardCodec>();
+
+// 多层管道级联(按添加顺序组成链)
+server.Add<StandardCodec>(); // 底层:粘包拆包 + 请求响应匹配
+server.Add<JsonCodec>(); // 上层:JSON 编解码
+```
+
+### 4.4 StandardCodec 请求-响应
+
+StandardCodec 使用 `DefaultMessage`,包含 Flag(1字节)、Sequence(1字节)、Length(2字节),
+支持自动序列号分配和请求-响应匹配。
+
+```csharp
+// 服务端 Echo 示例
+server.Add<StandardCodec>();
+server.Received += (sender, e) =>
+{
+ if (sender is INetSession session && e.Message is IPacket pk)
+ session.SendReply(pk, e); // 使用 SendReply 关联请求上下文
+};
+
+// 客户端请求-响应
+client.Add<StandardCodec>();
+var response = await client.SendMessageAsync(payload);
+```
+
+### 4.5 基类选择
+
+| 基类 | 适用场景 | 典型代表 |
+|------|---------|---------|
+| `MessageCodec<T>` | 需要粘包拆包和/或请求-响应匹配(内置 `IMatchQueue`、`Encode`/`Decode`) | `StandardCodec`、`LengthFieldCodec` |
+| `Handler` | 简单转换、帧协议、文本协议(轻量,仅 `Read`/`Write`/`Open`/`Close`) | `JsonCodec`、`SplitDataCodec`、`WebSocketCodec` |
+
+### 4.6 编解码器设计规范
+
+#### 4.6.1 粘包拆包(PacketCodec 模式)
+
+TCP 是字节流协议,必须处理粘包拆包。统一模式(完整实现见 4.7 模板):
+
+1. 每个连接独立的 `PacketCodec` 实例,存储在 `ss["Codec"]` 中
+2. 通过 `GetLength2` 委托告诉 `PacketCodec` 如何计算完整帧长度
+3. `PacketCodec.Parse()` 返回完整帧列表,自动缓存不完整数据
+
+**`GetLength2` 规范**(签名 `Int32 GetLength(ReadOnlySpan<Byte> span)`):返回帧完整长度(含头部),数据不足时返回 `0`。
+
+```csharp
+public static Int32 GetLength(ReadOnlySpan<Byte> span)
+{
+ if (span.Length < 4) return 0;
+ var reader = new SpanReader(span) { IsLittleEndian = true };
+ reader.Advance(2);
+ return 4 + reader.ReadUInt16(); // 头部4字节 + 负载长度
+}
+```
+
+#### 4.6.2 编码与内存管理
+
+- **`ExpandHeader(size)`**:编码时优先复用负载缓冲区前置空间写入头部,零拷贝;空间不足时创建 `OwnerPacket`,原包作为 `Next` 链节点
+- **`SpanWriter`**:配合 `ExpandHeader` 写入头部字段,注意 `IsLittleEndian` 大小端
+- **兜底释放**:`MessageCodec<T>.Write` 基类自动 `TryDispose`;`Handler` 子类需在 `Write` 的 `finally` 中手动调用
+- **对象池**:`DefaultMessage.Rent()` / `DefaultMessage.Return()` 减少 GC 压力
+
+#### 4.6.3 请求-响应匹配
+
+`MessageCodec<T>` 内置 `IMatchQueue`,流程:`Write` → `AddToQueue` 入队 → `Decode` 解码 → `Queue.Match` 按 `IsMatch` 匹配 → 唤醒 `SendMessageAsync` 的 `Task`。
+
+- 重载 `AddToQueue`:控制哪些消息入队(通常只有请求消息)
+- 重载 `IsMatch`:根据序列号等字段匹配请求和响应(见 4.7 模板)
+- `QueueSize`:匹配队列大小,默认 256
+- `Timeout`:等待响应超时,默认 30_000ms
+- `UserPacket`:为 `true` 时向上层传递 `Payload` 而非整个 `IMessage`,用于编码器级联
+
+#### 4.6.4 Close 清理
+
+**必须**在 `Close` 中执行 `ss["Codec"] = null` 清理 `PacketCodec`,否则 `MemoryStream` 缓存泄漏(见 4.7 模板)。
+
+#### 4.6.5 上下文扩展(IExtend)
+
+管道处理器通过 `IExtend` 在会话/上下文上传递元数据:
+
+| 键 | 用途 | 示例 |
+|---|------|------|
+| `"Codec"` | 每连接的 `PacketCodec` 实例 | 编解码器的 `Decode`/`Close` 中读写 |
+| `"Flag"` | 数据类型标记 `DataKinds` | `JsonCodec.Write` 设置 → `StandardCodec.Write` 消费 |
+| `"_raw_message"` | 原始请求消息 | `MessageCodec.Read` 设置 → `Write` 中创建响应时消费 |
+| `"TaskSource"` | `TaskCompletionSource` | 框架内部,`AddToQueue` 消费 |
+
+#### 4.6.6 多层管道级联
+
+- 底层编解码器处理粘包拆包和请求-响应匹配,上层处理数据格式转换
+- `UserPacket = true` 让底层向上层传递 `Payload` 而非整个 `IMessage`
+- 上层通过 `ext["Flag"]` 向底层传递数据类型标记
+
+### 4.7 自定义编解码器模板
+
+#### 方式一:继承 MessageCodec<T>(需要粘包/请求响应匹配)
+
+```csharp
+/// <summary>自定义协议编解码器</summary>
+public class MyCodec : MessageCodec<MyMessage>
+{
+ /// <summary>编码消息为数据包</summary>
+ protected override Object? Encode(IHandlerContext context, MyMessage msg)
+ {
+ return msg.ToPacket();
+ }
+
+ /// <summary>解码数据包为消息</summary>
+ protected override IEnumerable<MyMessage>? Decode(IHandlerContext context, IPacket pk)
+ {
+ if (context.Owner is not IExtend ss) yield break;
+
+ if (ss["Codec"] is not PacketCodec pc)
+ {
+ ss["Codec"] = pc = new PacketCodec
+ {
+ GetLength2 = MyMessage.GetLength,
+ MaxCache = MaxCache,
+ Tracer = (context.Owner as ISocket)?.Tracer
+ };
+ }
+
+ foreach (var item in pc.Parse(pk))
+ {
+ var msg = new MyMessage();
+ if (msg.Read(item)) yield return msg;
+ }
+ }
+
+ /// <summary>是否匹配响应</summary>
+ protected override Boolean IsMatch(Object? request, Object? response) =>
+ request is MyMessage req && response is MyMessage res
+ && req.Sequence == res.Sequence;
+
+ /// <summary>连接关闭时清理</summary>
+ public override Boolean Close(IHandlerContext context, String reason)
+ {
+ if (context.Owner is IExtend ss) ss["Codec"] = null;
+
+ return base.Close(context, reason);
+ }
+}
+```
+
+#### 方式二:继承 Handler(简单转换/帧协议)
+
+```csharp
+/// <summary>自定义帧编解码器</summary>
+public class MyFrameCodec : Handler
+{
+ /// <summary>读取数据(接收时)</summary>
+ public override Object? Read(IHandlerContext context, Object message)
+ {
+ if (message is IPacket pk)
+ {
+ // 解码:二进制 → 业务对象
+ var frame = MyFrame.Parse(pk);
+ message = frame;
+ }
+
+ return base.Read(context, message);
+ }
+
+ /// <summary>写入数据(发送时)</summary>
+ public override Object? Write(IHandlerContext context, Object message)
+ {
+ IPacket? owner = null;
+ if (message is MyFrame frame)
+ {
+ // 编码:业务对象 → 二进制
+ message = owner = frame.ToPacket();
+ }
+
+ try
+ {
+ return base.Write(context, message);
+ }
+ finally
+ {
+ owner.TryDispose(); // 兜底释放
+ }
+ }
+
+ /// <summary>连接关闭时清理缓存</summary>
+ public override Boolean Close(IHandlerContext context, String reason)
+ {
+ if (context.Owner is IExtend ss) ss["Codec"] = null;
+
+ return base.Close(context, reason);
+ }
+}
+```
+
+---
+
+## 5. 常见模式与最佳实践
+
+### 5.1 端口选择
+
+- 测试代码使用端口 `0`(系统自动分配随机端口),避免端口冲突
+- 正式服务指定固定端口
+- 启动后可通过 `server.Port` 获取实际监听端口
+
+### 5.2 协议选择
+
+| 场景 | 推荐 |
+|------|------|
+| 可靠传输、长连接 | `NetType.Tcp` |
+| 低延迟、广播、允许丢包 | `NetType.Udp` |
+| 同时支持(默认) | `NetType.Unknown` |
+| Web 浏览器通信 | `NetType.WebSocket` |
+
+### 5.3 会话管理
+
+- `UseSession = true`(默认):维护会话集合,支持群发、按 ID 查找
+- `UseSession = false`:不维护会话集合,减少内存开销,适合海量短连接
+- `SessionTimeout`:设置会话超时时间(秒),超时无数据自动断开
+- 会话中通过 `Items` 字典存储自定义数据
+
+### 5.4 日志分层
+
+| 属性 | 用途 | 建议 |
+|------|------|------|
+| `Log` | 服务器应用层日志 | 始终设置 |
+| `SessionLog` | 会话级别日志 | 调试时设置 |
+| `SocketLog` | 底层 Socket 日志 | 仅 DEBUG 时设置 |
+| `LogSend` / `LogReceive` | 收发数据内容日志 | 仅 DEBUG 时开启 |
+| `Tracer` | 应用层 APM | 生产环境追踪 |
+| `SocketTracer` | Socket 层 APM | 排查底层问题 |
+
+### 5.5 资源释放
+
+- 服务端:调用 `server.Stop(reason)` 或 `server.Dispose()`
+- 客户端:调用 `client.Close(reason)` 或 `client.Dispose()`
+- 会话自动随连接断开释放,无需手动管理
+- `ISocketClient` 实现 `IDisposable`,推荐 `using` 模式
+
+### 5.6 INetHandler 业务处理器
+
+通过重载 `NetServer.CreateHandler` 注入自定义业务处理器:
+
+```csharp
+class MyServer : NetServer<MySession>
+{
+ /// <summary>为会话创建网络数据处理器</summary>
+ public override INetHandler? CreateHandler(INetSession session) => new MyHandler();
+}
+```
+
+处理器在会话 `Start` 时初始化,`OnReceive` 前调用 `Process`,适合前置协议解析。
+
+---
+
+## 6. 常见错误
+
+- ❌ 在 `OnReceive` 中执行长时间阻塞操作(会影响其他连接的数据接收)
+- ❌ 不加管道编解码器直接调用 `SendMessageAsync`(无法匹配响应)
+- ❌ 混淆 `Send` 与 `SendMessage`:前者直接发原始数据,后者经过管道编码
+- ❌ 混淆 `SendMessage` 与 `SendReply`:响应消息必须用 `SendReply` 关联请求上下文
+- ❌ 忘记调用 `base.OnConnected()` / `base.OnDisconnected(reason)` / `base.OnReceive(e)`
+- ❌ 在会话中使用 `Task.Result` 或 `Task.Wait()`(导致死锁和线程池饥饿)
+- ❌ 使用固定端口编写测试(端口冲突),应使用 `Port = 0`
+- ❌ 服务端 SSL 未指定证书
+
+---
+
+## 7. 完整示例
+
+### 7.1 带 StandardCodec 的 Echo 服务
+
+```csharp
+// 服务端
+var server = new NetServer
+{
+ Port = 8080,
+ ProtocolType = NetType.Tcp,
+ Log = XTrace.Log,
+};
+server.Add<StandardCodec>();
+server.Received += (sender, e) =>
+{
+ if (sender is INetSession session && e.Message is IPacket pk)
+ session.SendReply(pk, e);
+};
+server.Start();
+
+// 客户端
+var client = new NetUri($"tcp://127.0.0.1:{server.Port}").CreateRemote();
+client.Add<StandardCodec>();
+client.Open();
+
+var response = await client.SendMessageAsync(new ArrayPacket("Hello".GetBytes()));
+```
+
+### 7.2 自定义会话服务器
+
+```csharp
+class ChatServer : NetServer<ChatSession> { }
+
+class ChatSession : NetSession<ChatServer>
+{
+ protected override void OnConnected()
+ {
+ base.OnConnected();
+ Send($"欢迎 [{Remote}] 进入聊天室!\r\n");
+ }
+
+ protected override void OnReceive(ReceivedEventArgs e)
+ {
+ base.OnReceive(e);
+ var msg = e.Packet?.ToStr();
+ if (msg.IsNullOrEmpty()) return;
+
+ // 广播给所有在线用户
+ var host = (this as INetSession).Host;
+ host.SendAllMessage($"[{ID}] {msg}");
+ }
+
+ protected override void OnDisconnected(String reason)
+ {
+ base.OnDisconnected(reason);
+ WriteLog("用户离开:{0}", reason);
+ }
+}
+```
+
+---
+
+(完)
diff --git a/.github/instructions/xcode.instructions.md b/.github/instructions/xcode.instructions.md
new file mode 100644
index 0000000..2a79c8e
--- /dev/null
+++ b/.github/instructions/xcode.instructions.md
@@ -0,0 +1,575 @@
+# XCode 协作指令
+
+本指令面向新生命团队(NewLife)开源数据中间件 XCode,帮助 Copilot 在 .NET 项目中正确使用 XCode 进行数据建模和实体操作。
+
+---
+
+## 1. XCode 定位与边界
+
+```
+NewLife.Core(基础库)→ copilot-instructions.md
+ ↓
+ NewLife.XCode(数据中间件)← 本指令
+ ↓
+ NewLife.Cube(Web 快速开发框架)→ cube.instructions.md
+```
+
+**本指令覆盖**:数据模型设计(Model.xml)、实体类生成与使用、数据库 CRUD 操作、运行时配置、项目初始化与 XCode 接入。
+**不包含**(由 `cube.instructions.md` 负责):Web 控制器、视图与前端、权限管理、魔方区域深度定制。
+
+### 1.1 支持的数据库
+
+| 常用 | 国产/信创 | 时序/嵌入 |
+|------|----------|----------|
+| SqlServer、MySql、SQLite、PostgreSQL、Oracle | 达梦(DaMeng)、人大金仓(KingBase)、瀚高(HighGo)、VastBase | TDengine、InfluxDB、NovaDb |
+
+> 另支持 DB2、Hana、IRIS、Access 等,完整列表见 `DatabaseType` 枚举。
+
+---
+
+## 2. 使用场景与快速入口
+
+### 2.1 场景一:已有项目接入 XCode
+
+1. 引入 NuGet 包:`dotnet add package NewLife.XCode`
+2. 创建或编辑 `Model.xml` 进行数据建模
+3. 执行 `xcode` 命令生成实体类
+4. 在业务代码中使用实体类进行数据操作
+
+### 2.2 场景二:从零创建新项目
+
+1. 安装模板:`dotnet new install NewLife.Templates`
+2. 创建数据类库:`dotnet new xcode -n {系统名}.Data`
+3. 创建应用项目:
+ - Web 应用:`dotnet new cube -n {系统名}Web`
+ - 控制台应用:`dotnet new nconsole -n {系统名}App`
+4. 编辑 `Model.xml` 进行数据建模
+5. 执行 `xcode` 生成实体类
+
+### 2.3 核心工作流
+
+```
+理解业务需求 → 数据建模(Model.xml) → 生成实体类(xcode) → 编写业务代码
+```
+
+**关键点**:无论哪种场景,核心都是 **充分理解业务需求,在 Model.xml 中设计合理的数据表结构**。
+
+---
+
+## 3. 环境准备
+
+### 3.1 前置要求
+
+```powershell
+# 检查 .NET SDK(要求 8.0+)
+dotnet --version
+
+# 安装全局工具 xcodetool
+dotnet tool install xcodetool -g
+```
+
+### 3.2 模板版本检查
+
+NewLife.Templates 模板会持续更新,使用前需检查版本:
+
+```powershell
+# 查看模板详情
+dotnet new details NewLife.Templates
+```
+
+**判定规则**:输出包含类似 `包版本: 1.1.2025.820-beta1836`
+- 其中 `1.1.2025.820` 表示 v1.1,发布日期为 2025-08-20
+- **要求**:发布日期需 > 2025-08-01(即严格晚于 2025-08-01)
+
+```powershell
+# 若未安装或版本过旧,执行安装/更新
+dotnet new install NewLife.Templates
+```
+
+> **强约束**:仅当未安装或发布日期 ≤ 2025-08-01 时才执行安装;否则保持现状,避免无谓变更。
+
+### 3.3 模板说明
+
+| 模板 | 命令 | 用途 |
+|------|------|------|
+| `xcode` | `dotnet new xcode -n Name.Data` | 数据类库项目 |
+| `cube` | `dotnet new cube -n NameWeb` | Web 管理后台 |
+| `nconsole` | `dotnet new nconsole -n NameApp` | 控制台应用 |
+
+---
+
+## 4. Model.xml 完整参考
+
+### 4.1 文件结构
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<EntityModel xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:schemaLocation="https://newlifex.com https://newlifex.com/Model202509.xsd"
+ xmlns="https://newlifex.com/Model202509.xsd">
+ <Option>
+ <!-- 全局配置 -->
+ </Option>
+ <Tables>
+ <Table>
+ <Columns>
+ <Column />
+ </Columns>
+ <Indexes>
+ <Index />
+ </Indexes>
+ </Table>
+ </Tables>
+</EntityModel>
+```
+
+### 4.2 Option 配置项
+
+| 配置项 | 说明 | 示例 |
+|--------|------|------|
+| `Namespace` | 命名空间 | `Zero.Data` |
+| `ConnName` | 数据库连接名 | `Zero` |
+| `Output` | 实体类输出目录 | `.\` |
+| `BaseClass` | 实体基类 | `Entity` |
+| `ChineseFileName` | 使用中文文件名 | `True` |
+| `Nullable` | 生成可空引用类型 | `True` |
+| `HasIModel` | 实现 IModel 接口 | `True` |
+| `ModelClass` | 模型类模板 | `{name}Model` |
+| `ModelsOutput` | 模型类输出目录 | `.\Models\` |
+| `ModelInterface` | 模型接口模板 | `I{name}` |
+| `InterfacesOutput` | 接口输出目录 | `.\Interfaces\` |
+| `ClassNameTemplate` | 类名模板 | `{name}Model`/`I{name}Dto` |
+| `DisplayNameTemplate` | 显示名模板 | `{displayName}` |
+| `ModelNameForCopy` | Copy 函数参数类型 | `{name}`/`I{name}` |
+| `ModelNameForToModel` | ToModel 转换目标类型 | `{name}`/`{name}DTO` |
+| `ExtendNameSpace` | 额外引用命名空间(逗号分隔) | `System.Xml.Serialization` |
+| `NameFormat` | 命名格式 | `Default`/`Upper`/`Lower`/`Underline` |
+| `DisplayName` | 魔方区域显示名 | `订单管理` |
+| `CubeOutput` | 魔方控制器输出目录 | `../../Web/Areas/Order` |
+
+### 4.3 Table 属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Name` | 实体类名 | `User` |
+| `TableName` | 数据库表名(可选,默认同 Name) | `sys_user` |
+| `Description` | 表说明 | `用户。用户账号信息` |
+| `ConnName` | 独立连接名(覆盖全局) | `Log` |
+| `BaseType` | 基类(支持实体继承) | `EntityBase` |
+| `InsertOnly` | 仅插入模式(日志表优化) | `True` |
+| `IsView` | 视图标识 | `True` |
+
+### 4.4 Column 属性完整参考
+
+#### 基础属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Name` | 属性名 | `UserName` |
+| `ColumnName` | 数据库列名(可选) | `user_name` |
+| `DataType` | 数据类型 | `Int32`/`Int64`/`String`/`DateTime`/`Boolean`/`Double`/`Decimal` |
+| `Description` | 字段说明 | `用户名。登录账号` |
+| `Length` | 字符串长度 | `50`/`200`/`-1`(大文本) |
+| `Precision` | 数值精度 | `18` |
+| `Scale` | 小数位数 | `2` |
+
+#### 主键与标识
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `PrimaryKey` | 主键 | `True` |
+| `Identity` | 自增标识 | `True` |
+| `Master` | 主字段(业务主要字段) | `True` |
+
+**主键设计约定**:
+- 普通表:`Int32` 自增 → `PrimaryKey="True" Identity="True"`
+- 大数据表:`Int64` 雪花 ID → `PrimaryKey="True" DataScale="time"`(不设 Identity)
+
+#### 约束与默认值
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Nullable` | 允许空 | `False` |
+| `DefaultValue` | 默认值 | `0`/`''`/`getdate()` |
+
+#### 映射关系(Map)
+
+格式:`表名@主键@显示字段@属性名`
+
+| 格式 | 说明 | 示例 |
+|------|------|------|
+| `Table@Id@Name` | 基本映射(三段) | `Role@Id@Name` |
+| `Table@Id@Name@RoleName` | 指定属性名(四段) | `Role@Id@Name@RoleName` |
+| `NS.Table@Id@Path@AreaPath` | 完整命名空间 | `XCode.Membership.Area@Id@Path@AreaPath` |
+
+#### 元素类型(ItemType)
+
+用于魔方前端渲染,常用值:`image`、`file`、`mail`、`mobile`、`url`、`TimeSpan`、`GMK`、`html`、`code`、`json`。详细用法见 `cube.instructions.md`。
+
+#### 显示选项(ShowIn)
+
+控制字段在魔方各区域(List/Detail/AddForm/EditForm/Search)的显示。推荐具名列表语法:
+
+```
+ShowIn="List,Search" # 仅 List 和 Search 显示
+ShowIn="-EditForm,-Detail" # 编辑表单和详情隐藏
+ShowIn="All,-Detail" # 全部显示,详情隐藏
+```
+
+区域别名:`List(L)`、`Detail(D)`、`AddForm(Add/A)`、`EditForm(Edit/E)`、`Search(S)`、`Form(F)`(同时控制 Add 和 Edit)
+
+**语法二:管道分隔**
+```
+ShowIn="Y|Y|N||A" # List=显示|Detail=显示|Add=隐藏|Edit=自动|Search=自动
+```
+
+**语法三:5字符掩码**
+```
+ShowIn="11110" # 1=显示, 0=隐藏, A/?/-=自动
+```
+
+#### 分表字段(DataScale)
+
+| 值 | 说明 |
+|----|------|
+| `time` | 大数据单表的时间字段(用于雪花 ID) |
+| `timeShard:yyMMdd` | 分表字段,按日期格式分表 |
+
+#### 其他属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Type` | 枚举类型 | `XCode.Membership.SexKinds` |
+| `Category` | 表单分组 | `登录信息`/`扩展` |
+| `Attribute` | 额外特性 | `XmlIgnore, IgnoreDataMember` |
+| `Model` | 是否包含在模型类中 | `False` |
+| `RawType` | 原始数据库类型 | `varchar(50)` |
+
+### 4.5 Index 属性
+
+| 属性 | 说明 | 示例 |
+|------|------|------|
+| `Columns` | 索引列(逗号分隔) | `Name`/`Category,CreateTime` |
+| `Unique` | 唯一索引 | `True` |
+
+### 4.6 完整示例
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<EntityModel xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+ xs:schemaLocation="https://newlifex.com https://newlifex.com/Model202509.xsd"
+ xmlns="https://newlifex.com/Model202509.xsd">
+ <Option>
+ <Namespace>Order.Data</Namespace>
+ <ConnName>Order</ConnName>
+ <Output>.\</Output>
+ <ChineseFileName>True</ChineseFileName>
+ <Nullable>True</Nullable>
+ <HasIModel>True</HasIModel>
+ <DisplayName>订单管理</DisplayName>
+ <CubeOutput>../../OrderWeb/Areas/Order</CubeOutput>
+ </Option>
+ <Tables>
+ <Table Name="Order" Description="订单。电商订单主表">
+ <Columns>
+ <Column Name="Id" DataType="Int64" PrimaryKey="True" DataScale="time" Description="编号" />
+ <Column Name="OrderNo" DataType="String" Master="True" Length="50" Nullable="False" Description="订单号" />
+ <Column Name="UserId" DataType="Int32" Map="User@Id@Name" Description="用户" />
+ <Column Name="Status" DataType="Int32" Type="Order.Data.OrderStatus" Description="状态" />
+ <Column Name="TotalAmount" DataType="Decimal" Precision="18" Scale="2" Description="总金额" />
+ <Column Name="Remark" DataType="String" Length="500" Description="备注" Category="扩展" />
+ <Column Name="CreateUser" DataType="String" Description="创建者" Model="False" Category="扩展" />
+ <Column Name="CreateTime" DataType="DateTime" Nullable="False" Description="创建时间" Category="扩展" />
+ <Column Name="UpdateTime" DataType="DateTime" Description="更新时间" Model="False" Category="扩展" />
+ </Columns>
+ <Indexes>
+ <Index Columns="OrderNo" Unique="True" />
+ <Index Columns="UserId" />
+ <Index Columns="Status,CreateTime" />
+ </Indexes>
+ </Table>
+ </Tables>
+</EntityModel>
+```
+
+---
+
+## 5. 实体类操作指南
+
+### 5.1 基础 CRUD
+
+```csharp
+// 新增
+var entity = new User { Name = "test", Password = "123456" };
+entity.Insert();
+
+// 查询单个(按主键)
+var user = User.FindByKey(1);
+// 查询单个(按条件)
+var user2 = User.Find(User._.Name == "test");
+
+// 查询列表
+var list = User.FindAll();
+var list2 = User.FindAll(User._.Status == 1, User._.Id.Desc(), null, 0, 10);
+
+// 更新
+user.Name = "newName";
+user.Update();
+
+// 删除
+user.Delete();
+
+// 保存(自动判断 Insert/Update)
+entity.Save();
+```
+
+### 5.2 高级查询
+
+```csharp
+// 分页查询
+var page = new PageParameter { PageIndex = 1, PageSize = 20 };
+var list = User.FindAll(User._.Status == 1, page);
+
+// 条件组合
+var where = new WhereExpression();
+where &= User._.Status == 1;
+where &= User._.CreateTime >= DateTime.Today;
+if (!key.IsNullOrEmpty()) where &= User._.Name.Contains(key);
+var list2 = User.FindAll(where, page);
+
+// 统计
+var count = User.FindCount(User._.Status == 1);
+
+// 查询最大/最小值
+var maxId = User.FindMax(User._.Id, null);
+```
+
+### 5.3 批量操作
+
+```csharp
+// 批量插入
+var list = new List<User>();
+for (var i = 0; i < 100; i++)
+{
+ list.Add(new User { Name = $"user{i}" });
+}
+list.Insert();
+
+// 批量更新(将 Status==1 的记录改为 Status=2)
+User.Update(User._.Status == 2, User._.Status == 1);
+
+// 批量删除
+User.Delete(User._.Status == 0);
+```
+
+### 5.4 异步操作
+
+```csharp
+var user = await User.FindAsync(User._.Id == 1);
+var list = await User.FindAllAsync(User._.Status == 1, page);
+await entity.InsertAsync();
+await entity.SaveAsync(); // 异步保存,用于日志等高频写入
+```
+
+### 5.5 缓存查询
+
+```csharp
+// 实体缓存(适用于小表)
+var list = User.FindAllWithCache();
+
+// 单对象缓存(按主键)
+var user = User.FindByKeyWithCache(1);
+```
+
+---
+
+## 6. 运行时机制
+
+### 6.1 实体拦截器(自动填充字段)
+
+XCode 内置全局拦截器,实体包含特定命名字段时自动触发,**无需业务代码手动赋值**:
+
+| 拦截器 | 匹配字段名 | 字段类型 | 行为 |
+|--------|-----------|---------|------|
+| `TimeInterceptor` | `CreateTime` | `DateTime` | Insert 时自动填充当前时间 |
+| | `UpdateTime` | `DateTime` | Insert/Update 时自动填充当前时间 |
+| `UserInterceptor` | `CreateUserID` | `Int32`/`Int64` | Insert 时填充当前用户 ID |
+| | `CreateUser` | `String` | Insert 时填充当前用户名 |
+| | `UpdateUserID` | `Int32`/`Int64` | Insert/Update 时填充当前用户 ID |
+| | `UpdateUser` | `String` | Insert/Update 时填充当前用户名 |
+| `IPInterceptor` | `CreateIP` | `String` | Insert 时填充客户端 IP |
+| | `UpdateIP` | `String` | Insert/Update 时填充客户端 IP |
+| `TraceInterceptor` | `TraceId` | `String` | Insert/Update 时填充链路追踪 ID |
+
+**建模约定**:这些自动填充字段通常设置 `Category="扩展"` + `Model="False"`,不暴露到模型类中。
+
+示例(Model.xml 中的扩展字段标准写法):
+```xml
+<Column Name="CreateUser" DataType="String" Description="创建者" Model="False" Category="扩展" />
+<Column Name="CreateUserID" DataType="Int32" Description="创建者" Model="False" Category="扩展" />
+<Column Name="CreateTime" DataType="DateTime" Description="创建时间" Model="False" Category="扩展" />
+<Column Name="CreateIP" DataType="String" Description="创建地址" Model="False" Category="扩展" />
+<Column Name="UpdateUser" DataType="String" Description="更新者" Model="False" Category="扩展" />
+<Column Name="UpdateUserID" DataType="Int32" Description="更新者" Model="False" Category="扩展" />
+<Column Name="UpdateTime" DataType="DateTime" Description="更新时间" Model="False" Category="扩展" />
+<Column Name="UpdateIP" DataType="String" Description="更新地址" Model="False" Category="扩展" />
+<Column Name="TraceId" DataType="String" Description="链路追踪" Model="False" Category="扩展" />
+```
+
+### 6.2 反向工程(自动建表)
+
+XCode 启动时自动对比实体模型与数据库表结构,根据 `Migration` 配置决定行为:
+
+| 模式 | 说明 | 适用场景 |
+|------|------|---------|
+| `Off` | 关闭,不检查不执行 | 生产环境(表结构由 DBA 管理) |
+| `ReadOnly` | 只读,检查差异但不执行 DDL | 生产环境排查 |
+| `On` | 打开,仅新建表/列(默认值) | 开发/测试环境 |
+| `Full` | 完全,可修改列类型、删除列/索引 | 开发初期快速迭代 |
+
+### 6.3 XCodeSetting 配置
+
+通过配置文件 `XCode.json` 或 `appsettings.json` 的 `XCode` 节控制运行时行为:
+
+| 配置项 | 默认值 | 说明 |
+|--------|--------|------|
+| `Debug` | `true` | 是否启用调试日志 |
+| `ShowSQL` | `true` | 是否输出 SQL 语句 |
+| `SQLPath` | `""` | SQL 日志独立目录,生产环境建议设置 |
+| `TraceSQLTime` | `1000` | SQL 慢查询阈值(毫秒) |
+| `UseParameter` | `false` | 参数化添删改查 |
+| `CommandTimeout` | `0` | 命令超时(秒),0 不限制 |
+| `RetryOnFailure` | `0` | 失败重试次数 |
+| `Migration` | `On` | 反向工程模式(见 6.2) |
+| `BatchSize` | `5000` | 批量操作数据量 |
+| `EntityCacheExpire` | `10` | 实体缓存过期时间(秒) |
+| `SingleCacheExpire` | `10` | 单对象缓存过期时间(秒) |
+
+**生产环境建议**:
+```json
+{
+ "XCode": {
+ "Migration": "Off",
+ "ShowSQL": false,
+ "SQLPath": "../SqlLog",
+ "TraceSQLTime": 500
+ }
+}
+```
+
+---
+
+## 7. 多模块项目结构
+
+对于复杂业务系统,建议按模块组织:
+
+```
+Zero.Data/
+├── Order/ # 订单模块
+│ ├── Order.xml # 订单模型
+│ ├── 订单.cs
+│ └── 订单明细.cs
+├── Product/ # 商品模块
+│ ├── Product.xml # 商品模型
+│ ├── 商品.cs
+│ └── 分类.cs
+└── Member/ # 会员模块
+ ├── Member.xml # 会员模型
+ └── 会员.cs
+```
+
+每个模块目录内有独立的 `*.xml` 模型文件,在各自目录执行 `xcode` 命令生成实体类。
+
+---
+
+## 8. xcode 命令参考
+
+```powershell
+# 在模型文件所在目录执行(自动查找所有 *.xml)
+xcode
+
+# 指定模型文件
+xcode Model.xml
+xcode Order.xml
+```
+
+**执行效果**:
+1. 读取 XML 模型文件
+2. 生成实体类(`*.cs`)
+3. 生成模型类(如配置了 `ModelClass`)
+4. 生成接口(如配置了 `ModelInterface`)
+5. 生成数据字典(`*.htm`)
+6. 生成魔方控制器(如配置了 `CubeOutput`)
+
+---
+
+## 9. 常见问题
+
+### 9.1 模型文件命名
+
+- 默认:`Model.xml`
+- 推荐:`{系统英文名}.xml` 或 `{模块名}.xml`
+- 复杂项目:每个模块目录一个模型文件
+
+### 9.2 实体类生成位置
+
+- 实体类生成在 `xcode` 命令执行目录
+- 可通过 `Output` 配置项指定输出目录
+- 魔方控制器通过 `CubeOutput` 指定
+
+### 9.3 数据库连接
+
+在应用配置文件中配置连接字符串:
+
+```json
+{
+ "ConnectionStrings": {
+ "Order": "Server=.;Database=Order;Uid=sa;Pwd=xxx"
+ }
+}
+```
+
+连接名对应 Model.xml 中的 `ConnName`。未配置连接字符串时,默认创建同名 SQLite 数据库。
+
+### 9.4 生成的代码能否手动修改
+
+实体类分为两个文件:
+- `实体名.cs`(如 `订单.cs`):自动生成的数据映射代码,**每次 `xcode` 会覆盖,禁止手动修改**
+- `实体名.Biz.cs`(如 `订单.Biz.cs`):业务扩展代码,仅首次生成,**可自由修改**
+
+需要调整字段、类型、索引时,应修改 `Model.xml` 后重新执行 `xcode`。
+
+### 9.5 如何调试 SQL
+
+配置 `XCodeSetting.ShowSQL = true`(默认开启),所有 SQL 输出到日志。设置 `SQLPath` 可将 SQL 日志独立存放。`TraceSQLTime` 控制慢查询阈值。
+
+### 9.6 与 Cube 的协作
+
+需要生成 Web 管理界面时:在 Model.xml 中配置 `CubeOutput` 指向 Web 项目的 Areas 目录,配置 `DisplayName` 作为区域名称,执行 `xcode` 自动生成控制器。深度定制见 `cube.instructions.md`。
+
+---
+
+## 10. Copilot 行为指引
+
+### 10.1 数据建模时
+
+1. **充分理解业务**:在设计表结构前,确保理解业务场景和数据关系
+2. **合理设计主键**:
+ - 普通表:`Int32` + `PrimaryKey="True" Identity="True"`
+ - 大数据表:`Int64` + `PrimaryKey="True" DataScale="time"`(雪花 ID)
+3. **必要的索引**:为查询条件字段添加索引
+4. **字段长度**:String 类型必须指定合理的 `Length`
+5. **扩展字段**:`CreateTime`/`UpdateTime`/`CreateUser`/`UpdateUser`/`CreateIP`/`UpdateIP` 等由拦截器自动填充(见 6.1),设置 `Model="False" Category="扩展"`
+
+### 10.2 生成代码时
+
+1. 确保在正确目录执行 `xcode`
+2. 生成后检查编译是否通过
+3. 如需修改生成的代码,应修改 Model.xml 后重新生成
+4. 业务逻辑写在 `.Biz.cs` 文件中
+
+### 10.3 边界意识
+
+- 数据模型和实体操作 → 本指令
+- Web 控制器和界面 → `cube.instructions.md`
+- 基础编码规范 → `copilot-instructions.md`
diff --git a/MapApi/MapApi.csproj b/MapApi/MapApi.csproj
index 896036a..e588dcc 100644
--- a/MapApi/MapApi.csproj
+++ b/MapApi/MapApi.csproj
@@ -1,9 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk.Web">
+<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
- <AssemblyTitle>地图接口平台</AssemblyTitle>
- <Description>企业内部地图接口平台,为各应用系统提供统一化的地图接口</Description>
+ <AssemblyTitle>企业地图接口平台</AssemblyTitle>
+ <Description>面向企业内部的统一地图接口平台,聚合多地图厂商能力并提供标准化地理服务访问入口</Description>
<Company>新生命开发团队</Company>
<Copyright>©2002-2026 新生命开发团队</Copyright>
<VersionPrefix>1.1</VersionPrefix>
diff --git a/NewLife.Map/NewLife.Map.csproj b/NewLife.Map/NewLife.Map.csproj
index 5392c7a..1d6b1f5 100644
--- a/NewLife.Map/NewLife.Map.csproj
+++ b/NewLife.Map/NewLife.Map.csproj
@@ -1,8 +1,8 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;net461;netstandard2.0;netstandard2.1</TargetFrameworks>
- <AssemblyTitle>地图组件库</AssemblyTitle>
- <Description>地图组件库,封装百度地图、高德地图和腾讯地图</Description>
+ <AssemblyTitle>统一地图组件库</AssemblyTitle>
+ <Description>统一封装百度、高德、腾讯、天地图与企业聚合地图接口,提供地理编码、逆地理、距离计算、坐标转换与多Key熔断能力</Description>
<Company>新生命开发团队</Company>
<Copyright>©2002-2026 新生命开发团队</Copyright>
<VersionPrefix>2.6</VersionPrefix>
diff --git a/Test/Test.csproj b/Test/Test.csproj
index cad5f90..aba6815 100644
--- a/Test/Test.csproj
+++ b/Test/Test.csproj
@@ -1,8 +1,10 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
+ <AssemblyTitle>地图组件调试程序</AssemblyTitle>
+ <Description>用于本地联调与示例验证地图组件库及其企业地图接口能力的控制台测试程序</Description>
<OutputPath>..\Bin\Test</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<ImplicitUsings>enable</ImplicitUsings>
diff --git a/XUnitTest/XUnitTest.csproj b/XUnitTest/XUnitTest.csproj
index e8e1e2c..d04e48d 100644
--- a/XUnitTest/XUnitTest.csproj
+++ b/XUnitTest/XUnitTest.csproj
@@ -1,7 +1,9 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
+ <AssemblyTitle>地图组件单元测试</AssemblyTitle>
+ <Description>用于验证地图组件库各地图提供者在地理编码、逆地理编码与坐标转换等核心能力上的行为正确性</Description>
<OutputPath>..\Bin\UnitTest</OutputPath>
<IsPackable>false</IsPackable>