Coding Agent 落地 C# 项目时,工程师最常问的几类问题,几乎全部依赖语义信息,而不是字符串匹配:这个方法被哪些地方调用了,只被测试代码用吗;某个字段、属性、事件、类型被哪些源码位置引用了;哪些类实现了这个接口;哪些成员重写了这个虚方法或接口成员;哪些声明在静态分析下零入边,可不可以删;哪些方法只在测试工程里被引用,可以做依赖反向。 如果只让 Agent 跑 grep,它能给出名字很像的候选,但无法告诉调用者——到底绑定的是哪个重载、来自哪个 project、对应哪个 TFM(target framework moniker)、是不是接口的实现。Graphify C# 的回答是:把工程文件通过 MSBuild 加载,交给 Roslyn 解析每个符号到底指什么,再把编译器已经解出来的边,以 nodes / edges / hyperedges 三类结构写进 JSON。 它能给到的结果,对应到 Rider 的开发体验里是这样的:Find Usages 转为一组带方向的、编译器已解析的 calls 与 references 边;Jump to Implementation 转为一组指回接口契约的 implements 边;继承体系浏览对应 inherits 与 overrides 边;重载与泛型消歧给出稳定的 symbol identity,带绑定后的签名信息;大仓库浏览给每条边都附带 project、TFM、源码位置、provenance 元数据。 这套语义事实交给 Agent 之后,Agent 不再"猜"哪些方法在测试工程里被调用、哪些是死代码候选、哪些引用应该跟到接口契约——所有判断都基于编译器已经确认的事实。

二、技术架构与工作原理

Graphify C# 的核心是一个无头(headless)的 Roslyn/MSBuild 索引器。它不依赖任何 IDE,不依赖任何 Graphify 主产品,也不需要被分析的工程编译产物 DLL。给定一个 .sln、.slnx、.csproj 或者 SDK 风格的文件型 .cs 应用,工具会:通过 MSBuild 加载工程,准备 Roslyn 工作区;让 Roslyn 解析每个符号的真实定义,处理重载消歧、泛型实参绑定、跨 project 调用;输出稳定命名的符号、指向具体声明的关系边,以及来源位置和 provenance;写入一份完整的 JSON 文档(默认 ./graphify-out/csharp.json),包含 nodes、edges、hyperedges 三个顶层结构。

工具本身通过 NuGet 分发为 dotnet tool,一条命令即可安装;调用也是一条命令,指定输入 .sln、根目录、配置和输出路径即可。它的可索引对象非常全:命名空间、类、结构体、接口、record、enum、delegate;构造函数、方法、运算符、局部函数;属性、索引器、字段、enum 项、事件;参数、局部变量、类型参数、别名、标签、查询范围变量。能解析的边也覆盖到:直接调用、构造函数调用、方法组、成员访问;字段引用、类型引用、特性引用、泛型实参、typeof 表达式、声明头引用;inherits、implements、overrides;编译器选中的运算符、转换、解构、foreach、await、using、模式匹配、range、集合表达式;实参到形参的绑定;跨 project、感知重载、感知 project/TFM 的身份。

不支持的语义形状会被明确地报成 diagnostic,而不是静默丢弃或让整个提取流程崩溃——这是工具作者特别强调的边界设计。

三、增量、监听与语言版本

对 Coding Agent 真正友好的能力,是它能保持工作区热度(warm)。一旦工程发生变化,增量索引会接管,不需要每次都重新走完整流程。监听器持续让 Roslyn 工作区保持热度,后台预处理发生变化的 project;普通的 graphify-csharp 调用充当显式的 refresh barrier,只有在完整 JSON 快照更新后才返回。如果当前没有匹配的 watcher 在跑,同一条命令就会退化为一次性 refresh。--rebuild 选项可以强制失效增量缓存。

语言版本上,工具随包发布两份工具资源:一份对应 .NET 10 加 Roslyn 5.9 加 C# 14;另一份对应 .NET 11 SDK 自带的 Roslyn 加 C# 15 preview。安装或更新时通过 --framework 选择工具运行时与 Roslyn 资源,通过 --target-framework 决定被分析的多目标工程里具体用哪一个 TFM 编译;单目标工程不需要指定后者。

四、给 Agent 用的 Skill 与项目约定

工具自带一份 SKILL.md,作为消费端使用指南。它不包含提取器的开发或发布流程,只讲 Agent 怎么用装好的 CLI:刷新索引、沿边走、解释静态分析的边界。在 Codex 兼容的项目里,一行 curl 就能装上。Claude Code 用对应的 .claude/skills 路径。安装或更新 skill 后需要 reload Agent 会话。

如果项目不用 skill,可以直接把一段提示写进项目说明:对 C# 结构和引用问题,回答前先用 graphify-csharp 刷新 csharp.json。通过 symbol_key 标识声明,检视 incoming 的 calls 与 references 边。把零入边当作"观察到的静态证据",不是"运行时不可达"的证明。

官方列出的高频 Agent 提问包括:这个重载或构造函数被谁调用;哪些声明引用了这个字段、属性、事件或类型;哪些类实现了这个接口;哪些成员重写了这个虚成员或接口成员;哪些声明零入边;哪些方法只在测试工程里被引用。

五、与 Rider、ReSharper、NDepend、JetBrains MCP 的边界

Graphify C# 在 HN 主帖里被反复与几款已有产品比较,作者明确划清了产品边界:Rider / ReSharper 提供 IDE 内的交互式导航、inspections、refactoring、quick fix——它们面向坐在 IDE 前的人类开发者;NDepend 是商业化、覆盖更广的架构与代码质量套件,围绕依赖分析、指标、规则、报告、基线、可视化展开;Graphify C# 提供的是源代码层面的 C# 语义证据,无头、开放格式,面向 Coding Agent;JetBrains 的 MCP 服务器允许 Agent 通过项目索引查询 Find Usages,但前提是 Rider IDE 在后台运行、工程已经加载并建立索引;GitHub Copilot 在云端缓存里维护一份语义索引,给 SaaS 仓库(以及微软已经持有源码的 GitHub/Azure DevOps)用,但需要 opt-in。

Graphify C# 跟 JetBrains MCP、Copilot 索引的差别,作者归结为三点:开源 MIT、按需 dump 一份可移植 JSON、跟 IDE 是否运行解耦。这意味着 CI 可以拿这份 JSON 做门禁、Agent 可以不依赖 MCP 协议、消费端可以用 jq / C# / Python / 任意下游工具直接处理,批量问答也不再依赖 IDE 后台。

六、静态分析的天花板与边界

工具作者在文档里专门留了一段边界声明:C# 语言的静态分析并不等于运行时可达性证明。反射、依赖注入、原生回调、动态调用,以及没加载进编译的代码,都可能造出运行时的真实关系,但不会出现在 edges 里。具体到产品语义:零入边等于静态观察到的零引用,不是运行时不可达;"仅测试使用"取决于工程或命名空间的分类约定;删除候选仍需人工判断。

这个边界不是缺陷,是工具的诚实。它把"静态能观察什么"明示出来,而不是伪装成运行时证明。这一姿态也是为什么 HN 上有用户评价 Agent 一直以来最大的痛点就是没有这种经过编译器验证的事实。

七、Show HN 当天的高质量反馈

主帖发布后,几个方向的反馈特别值得关注。社区开发者 质疑:为什么微软和 JetBrains 不自己出,这看起来就是 Roslyn 设计来干的事。作者回应:愿意直接交给微软维护,先 MIT 放出,是希望社区能跟上 C# 新版本节奏。社区开发者 提 JetBrains 的 MCP 服务也能让 Agent 查 Find Usages。差异是 Graphify C# 不基于 MCP,可以 dump 可移植 JSON,跟 Rider 是否启动解耦。社区开发者 已经把 Graphify C# 改造进 Unity Package 的开发工作流,把它当作外部分析工具,把 skill 适配到 Unity 工程里。社区开发者 担心大库 JSON 体积,作者实测自己仓库已经超过 600MB,确实存在大规模时 JSON 不一定最优的问题,SQLite 可能更合适。社区开发者 确认它能直接喂给 Graphify-Labs/graphify,不需要重新映射输出格式。

这些反馈组合起来说明一件事:工具找到了一个真实的、跨工程规模都成立的需求,且作者选择的形态——开源加无头加 JSON dump——正是与 IDE 商业产品、闭源云端索引都形成差异化的那条路径。

八、对 Harness 工具链的实际意义

把视角拉到 Coding Agent 的 harness(脚手架、工具集、调度框架)层面,Graphify C# 给出的是新基线。第一,Agent 第一次可以靠编译器事实回答"测试是否引用""接口实现""重写关系",而不是凭概率猜。第二,这份 JSON 可以直接接入 CI 做"死代码""纯测试实现""无人调用"等门禁规则,不需要搭数据库或商业工具。第三,跨 IDE、跨编辑器、跨 Agent 框架,只要能读 JSON,就能复用同一份语义事实——意味着 harness 设计可以从"依赖某个 IDE 进程"切到"消费一份可移植快照"。第四,把"零入边"明确为静态证据而非运行时不变量,等于给 Agent 设了一条诚实线——它必须把这种判断留给人或后续工具,而不是直接给最终结论。

所以无论是 LangGraph、AutoGen 这种自建 Agent 框架,还是 Codex、Claude Code 这种托管 Agent,都可以把它当作一项"基础设施级"的语义证据源。这条工具链一旦稳定下来,C# 工程里 Coding Agent 的可靠性会显著拉高——尤其是中型到大型、跨多个 project 与 TFM 的企业级工程。

九、什么时候不用它

工具也明确写出了不擅长的场景:纯反射调用的链路、运行时通过 DI 容器解析的接口、动态编译的脚本,都不会以边的方式出现。如果你主要在写 Unity 运行时反射、ASP.NET Core 中间件动态加载、MEF 组合,这些场景下 Roslyn 能观察到的边只是冰山一角,不能拿来当唯一判据。

另一种边界是规模:作者自己仓库的 JSON 已经超过 600MB。对几百万行 LOC 的工程,JSON 的查询效率与内存占用开始成为问题,这时切换到 SQLite 或专用的图存储可能是更现实的选择,这也是 Graphify 自身在做的方向。

最后一点:它不是 IDE 替代品,没有 Quick Fix、没有 Refactoring、没有 Inspections,不会主动建议改代码。它只把语义事实摆出来,剩下的判断留给 Agent 或人类。

十、Harness 工作流的实操建议

如果要把 Graphify C# 接到现有的 Coding Agent 工作流里,推荐的顺序是:在仓库根目录安装 dotnet tool,装 SKILL.md 到对应的 skills 目录;在仓库说明文件里明确"回答 C# 结构问题前先刷新 csharp.json"的硬约定;CI 里加一道 gate,跑监听模式在 PR 期间持续维护索引,作为"是否引入新 dead code、跨工程耦合"的事实来源;让 Agent 学会用 jq 处理 csharp.json,而不是走 MCP 或 IDE 集成;把零入边、未被任何测试覆盖的纯生产方法这类发现,放进 PR 评审的辅助证据列表,而不是直接当成删除建议。

这样落下来,C# 工程的 Coding Agent 才真正跨过"文本匹配代替编译器"这条老坎,站到 2026 年的新基线上。