使用BenchmarkDotNet时System.Text.Json源生成器缺失TypeInfoResolver异常
解决.NET 9中BenchmarkDotNet测试System.Text.Json源生成器Serialization模式的异常问题
问题原因
BenchmarkDotNet在编译基准测试项目时采用独立编译上下文,可能导致System.Text.Json源生成器生成的序列化逻辑未被正确加载或引用——尤其是GenerationMode=Serialization时,生成的针对性序列化代码可能因编译器优化或编译环境差异被忽略。
解决方案
1. 确保源生成上下文类的正确定义
检查DataSourceGenerationContext必须为partial类,配置需符合规范:
[JsonSerializable(typeof(Data), GenerationMode = JsonSourceGenerationMode.Serialization)] public partial class DataSourceGenerationContext : JsonSerializerContext { }
partial关键字是源生成器生成实现代码的必要条件,不能省略。- 若需全局序列化规则,可添加
[JsonSourceGenerationOptions]特性自定义配置。
2. 在基准测试中显式引用生成的类型元数据
不要直接传递DataSourceGenerationContext.Default作为TypeInfoResolver,需明确指定生成的类型属性:
[Benchmark] public string SerializeData() { return JsonSerializer.Serialize(_testData, DataSourceGenerationContext.Default.Data); } [Benchmark] public Data DeserializeData() { return JsonSerializer.Deserialize(_jsonString, DataSourceGenerationContext.Default.Data)!; }
这种写法能避免编译器因未直接使用生成的元数据而优化掉相关代码。
3. 配置项目编译选项确保源生成器正常工作
在基准测试项目的.csproj中添加以下设置:
<PropertyGroup> <TargetFramework>net9.0</TargetFramework> <Nullable>enable</Nullable> <!-- 强制保留源生成器输出,方便排查问题 --> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="BenchmarkDotNet" Version="0.13.12" /> <PackageReference Include="System.Text.Json" Version="9.0.0" /> </ItemGroup>
4. 优化BenchmarkDotNet配置避免编译异常
在基准测试类中添加必要特性,并明确指定运行时:
[MemoryDiagnoser] [SimpleJob(RuntimeMoniker.Net90)] public class JsonBenchmarks { private Data _testData = new Data { Id = 1, Name = "Test", Timestamp = DateTime.UtcNow }; private string _jsonString = string.Empty; [GlobalSetup] public void Setup() { // 提前完成序列化初始化,避免基准测试包含额外开销 _jsonString = JsonSerializer.Serialize(_testData, DataSourceGenerationContext.Default.Data); } // 基准测试方法... }
5. 验证源生成器输出
查看项目根目录下的Generated文件夹,确认是否生成了DataSourceGenerationContext.g.cs文件,且文件中包含Data类型的序列化/反序列化逻辑。若未生成,检查项目是否启用了源生成器(.NET 9默认启用)。
额外说明
- 不要依赖
JsonSerializerIsReflectionEnabledByDefault=true绕过问题,这会回退到反射模式,完全失去源生成器的性能优势。 GenerationMode=Metadata能正常运行,说明元数据生成逻辑没问题,但Serialization模式需要生成更具体的序列化代码,需确保这些代码被BenchmarkDotNet的编译上下文正确包含。
内容的提问来源于stack exchange,提问作者Ricardo Peres
相关产品推荐
相关产品推荐

