自定义依赖AdditionalFiles的IIncrementalGenerator如何支持Hot Reload?
增量源生成器在Hot Reload时不触发的解决办法
问题场景
我在解决方案的一个项目中实现了如下增量源生成器:
[Generator] public sealed class AvaloniaXamlSourceGeneraor : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { var axamlFiles = context.AdditionalTextsProvider .Where(static file => file.Path.EndsWith(".axaml", StringComparison.OrdinalIgnoreCase)); var axamlFileContents = axamlFiles.Select((text, cancellationToken) => (name: Path.GetFileNameWithoutExtension(text.Path), ContentDisposition: text.GetText(cancellationToken)!.ToString())); context.RegisterSourceOutput( axamlFileContents, static (context, compilation) => { context.AddSource(compilation.name + ".gen.cs", $@" class {compilation.name}__Gen {{ }} "); }); } }
在另一个包含.axaml文件的项目中引用该生成器项目后,构建时生成器能正常工作,生成的类会被编译到输出程序集。但启用Visual Studio Hot Reload调试时,修改C#代码可以触发Hot Reload,修改.axaml文件却不会重新调用生成器,输出窗口Hot Reload部分显示:
08:45 29.85 Checking for updates... 08:45 30.12 No changes were found.
解决办法
要让源生成器在Hot Reload时响应.axaml文件的修改,需做以下调整:
为增量源添加追踪标识
当前实现中,AdditionalTextsProvider虽能获取.axaml文件,但需为其添加追踪名称,让Roslyn能检测到文件内容变更。修改生成器代码:var axamlFiles = context.AdditionalTextsProvider .Where(static file => file.Path.EndsWith(".axaml", StringComparison.OrdinalIgnoreCase)) .WithTrackingName("AxamlFiles"); // 添加追踪名称,确保变更被识别配置项目文件触发增量编译
在包含.axaml文件的项目的.csproj中添加以下配置,确保.axaml文件变更会触发增量编译和Hot Reload:<ItemGroup> <AdditionalFiles Include="**\*.axaml" /> <UpToDateCheckInput Include="**\*.axaml" /> </ItemGroup>AdditionalFiles:明确将.axaml标记为编译过程的附加输入文件UpToDateCheckInput:让Visual Studio的最新性检查识别文件变更,触发增量编译与生成器执行
验证增量逻辑正确性
确保生成器的Select操作基于文件内容而非仅路径(当前代码已满足),同时避免生成逻辑中引入非确定性代码,否则会破坏增量更新机制。更新Visual Studio版本
旧版本Visual Studio在Hot Reload与增量源生成器的兼容性上存在bug,需使用Visual Studio 2022 17.4及以上版本,这类版本对增量生成器的Hot Reload支持更完善。
内容的提问来源于stack exchange,提问作者Sebastien Pellizzari
相关产品推荐
相关产品推荐

