C#增量源代码生成器未运行,请求排查问题
增量源代码生成器未触发、无文件生成问题排查
我想要创建一个增量源代码生成器,用于读取JSON文件并生成对应的类。但构建解决方案时没有生成任何文件,甚至生成器中的调试语句也未触发。
生成器项目配置
<PropertyGroup> <TargetFramework>netstandard2.0</TargetFramework> <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules> <IsRoslynComponent>true</IsRoslynComponent> <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.5.0" PrivateAssets="all" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> </ItemGroup> <ItemGroup> <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" /> </ItemGroup>
应用项目引用方式
<ItemGroup> <ProjectReference Include="..\SourceGenerators\SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> </ItemGroup>
生成器代码
[Generator] public class MetricsSourceGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext initContext) { System.Diagnostics.Debugger.Launch(); var textFile = initContext.AdditionalTextsProvider.Where(file => file.Path.Contains("Potato")); var contentProvider = textFile.Select((text, cancellationToken) => text.GetText(cancellationToken).ToString()); initContext.RegisterSourceOutput(contentProvider, (sourceProductionContext, fileContents) => { var metricDefinitions = JsonConvert.DeserializeObject<MetricDefinitions>(fileContents); foreach (var metric in metricDefinitions.Metrics) { var source = GenerateClassSourceCode(metric); sourceProductionContext.AddSource(metric.Name + "AnalyticsCounter.cs", SourceText.From(source, Encoding.UTF8)); } }); } private string GenerateClassSourceCode(MetricDefinition metric) { var className = metric.Name + "AnalyticsCounter"; var dimensionsOwnParameters = string.Join(", ", metric.Dimensions.Select(dimensionName => $"string {dimensionName}")); var dimensionsTrackValueParameters = string.Join(", ", metric.Dimensions); return $@" // <auto-generated/> using System.Collections.Generic; using Microsoft.ApplicationInsights; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This class is auto-generated by {this.GetType().Name}. Please DO NOT modify it manually! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ namespace App.DataLayer.Analytics.Metrics {{ public class {className} : AnalyticsCounter {{ public {className}(TelemetryClient telemetryClient) : base(""{metric.Name}"", telemetryClient) {{ }} public void Increment({dimensionsOwnParameters}) {{ Metric.TrackValue(1, {dimensionsTrackValueParameters}); }} }} }} "; } } public class MetricDefinitions { public MetricDefinition[] Metrics { get; set; } } public class MetricDefinition { public string Name { get; set; } public bool IsSimpleCounter { get; set; } public string[] Dimensions { get; set; } }
请问我哪里操作有误?是否需要采用其他构建方式?
问题排查与解决方案
1. JSON文件未标记为AdditionalText
生成器依赖AdditionalTextsProvider获取文件,若目标JSON文件未被识别为AdditionalText,生成器不会触发。需在应用项目中将JSON文件的BuildAction设置为AdditionalFiles:
<ItemGroup> <AdditionalFiles Include="**/Potato*.json" /> </ItemGroup>
确保文件路径包含"Potato",匹配代码中的过滤条件file.Path.Contains("Potato")。
2. 生成器项目依赖配置问题
- 增量生成器无需引用
Microsoft.CodeAnalysis.CSharp.Workspaces,替换为轻量化的Microsoft.CodeAnalysis.CSharp包:<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" PrivateAssets="all" /> Newtonsoft.Json未设置PrivateAssets="all",可能引发依赖冲突,修改为:<PackageReference Include="Newtonsoft.Json" Version="13.0.2" PrivateAssets="all" />
3. 调试语句的局限性
System.Diagnostics.Debugger.Launch()在常规编译环境中可能无法触发(生成器运行在编译进程内),改用诊断输出验证生成器是否启动:
initContext.ReportDiagnostic(Diagnostic.Create( new DiagnosticDescriptor("GEN001", "Generator Started", "Metrics生成器已初始化", "Generator", DiagnosticSeverity.Info, true), Location.None));
可在VS的「错误列表」中查看该诊断信息。
4. 生成代码的语法错误
生成的构造函数代码存在双引号转义错误:base(""{metric.Name}"", telemetryClient)会生成无效的字符串格式,修改为:
base($"{metric.Name}", telemetryClient)
语法错误会导致生成的代码无法编译,VS会自动隐藏错误的生成文件,因此你看不到输出结果。
5. 构建缓存与路径问题
- 清理解决方案,删除
bin、obj文件夹后重新构建,避免旧缓存干扰。 CompilerGeneratedFilesOutputPath默认在生成器项目目录下,若需在应用项目中查看生成文件,需在应用项目的PropertyGroup中添加:<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
6. 增量生成器逻辑的健壮性优化
添加空值检查,避免空引用异常导致生成器崩溃:
var contentProvider = textFile.Select((text, cancellationToken) => { var textContent = text.GetText(cancellationToken); return textContent?.ToString() ?? string.Empty; });
同时在反序列化后检查metricDefinitions和metricDefinitions.Metrics是否为空:
if (metricDefinitions?.Metrics == null) return;
内容的提问来源于stack exchange,提问作者Michael Tontchev
相关产品推荐
相关产品推荐

