源代码生成器在编译时分析标记类型并生成序列化代码,避免运行时反射开销。1. 它基于Roslyn解析语法树和语义信息;2. 扫描如[JsonSerializable]等特性标识的类型;3. 自动生成高效、强类型的序列化方法;4. 以System.Text.Json为例,在编译时生成PersonContext包含映射表和读写逻辑;5. 调用时直接使用生成代码提升性能;6. 可自定义实现ISourceGenerator接口,结合语法接收器捕获目标类型;7. 为[GenerateSerializer]标记类生成WriteTo/ReadFrom方法;8. 优势包括支持AOT、消除反射、深度优化;9. 限制是仅处理编译时可见类型,无法处理运行时泛型实例;10. 调试需启用特殊模式。该机制将运行时负担前移,使序列化高效透明。

.NET 中的源代码生成器通过在编译期间分析代码结构,自动生成与序列化相关的类型和方法,从而避免运行时反射带来的性能开销。它不依赖外部工具或运行时动态生成代码,而是在编译时将序列化逻辑直接嵌入到最终程序集中。
源代码生成器如何工作
源代码生成器是 .NET Compiler Platform(Roslyn)的一部分,能够在编译过程中读取用户代码中的语法树和语义信息,并根据特定规则生成新的 C# 代码文件。这些生成的代码与开发者编写的代码一起参与编译,就像手动编写的一样。
对于序列化场景,生成器会:
- 扫描标记了特定属性(如 Serializable 或自定义特性)的类型
- 分析类型的字段和属性结构
- 生成对应的序列化/反序列化方法实现
- 输出为可编译的 C# 源码,注入到项目中
以 System.Text.Json 源生成器为例
.NET 6 引入了 JsonSourceGenerator,允许提前生成 JSON 序列化支持代码。
使用方式如下:
// 定义一个数据模型并关联生成器 [JsonSerializable(typeof(Person))] partial class PersonContext : JsonSerializerContext { }编译时,生成器会:
- 识别 Person 类型的公共属性
- 生成高效的序列化读写器方法
- 构建属性名到访问器的映射表
- 避免运行时使用反射解析类型结构
这样调用 JsonSerializer.Serialize(value, PersonContext.Default.Person) 时,就能直接使用生成的强类型序列化逻辑,提升性能。
自定义序列化生成器实现思路
如果需要为二进制协议或特定格式生成代码,可以创建自己的源生成器:
- 实现 ISourceGenerator 接口
- 注册语法接收器来捕获目标类型(如带有 [Message] 特性的类)
- 在 Execute 方法中生成类似 WriteTo(Stream) 和 ReadFrom(ReadOnlySpan) 的方法体
- 使用 Microsoft.CodeAnalysis.CSharp.Syntax API 构建语法树,或拼接字符串模板
例如,对以下类型:
[GenerateSerializer] public partial class User { public int Id { get; set; } public string Name { get; set; } }生成器可自动创建 User.Serialize 和 User.Deserialize 方法,内含按字段顺序写入/读取的逻辑。
优势与限制
源代码生成器用于序列化的主要优势在于:
- 编译时确定逻辑,运行时无需反射
- 可做深度优化,如跳过空检查、常量折叠
- 支持 AOT 编译,适合 NativeAOT 或 Blazor WebAssembly
但也存在一些限制:
- 只能处理编译时可见的类型
- 无法处理运行时才确定的泛型实例
- 调试生成的代码需启用源生成器调试模式
基本上就这些。源代码生成器让序列化既高效又透明,关键是把原本延迟到运行时的工作提前完成。不复杂但容易忽略细节。










