从零实现增量源生成器 · 第 10 / 17 篇
ToString 渲染层到底在解决什么问题
代码渲染不只是拼一段字符串,它要负责重新打开命名空间、嵌套类型和目标类型,并保证输出代码可编译。
到了渲染层,很多人会本能地觉得“这部分最简单”。实际上,渲染层虽然不碰复杂语义,但非常容易制造编译级回归。
当前项目的渲染顺序很明确:
- 先补
#nullable enable - 再写命名空间
- 再逐层重新打开外层嵌套类型
- 最后在目标类型里输出
ToString()
为什么要重新打开外层类型
因为目标类型如果位于嵌套结构中,生成文件必须在同样的结构里重新声明分部类型,编译器才能把两边合并起来。
这也是为什么当前项目专门维护了 ContainingTypes。如果外层结构丢了,生成代码即使文本上看起来像对的,也会在编译期出问题。
ToString 表达式里真正重要的细节
当前实现对需要空值防护的属性会走:
?.ToString() ?? "null"
而不是一律直接插值。这种处理看起来像小事,但会直接决定引用类型和可空值类型的输出行为是否稳定。
渲染层的目标不是“聪明”
渲染层越机械越好。它只需要忠实消费前面已经整理好的模型,然后生成一份可编译、可读、可测试的文本。真正的判断应该尽量留在前面的发现和建模阶段。
教程导航
继续阅读
当前文章已经挂到教程顺序中,建议按相邻章节继续。