无文件I/O下通过RegisterPostInitializationOutput复制枚举源文件至编译
解决方案:利用嵌入式资源同步枚举定义
核心思路是把生成器项目中ConfigFlags的源文件打包为嵌入式资源,在生成器运行时从自身程序集读取资源内容,再通过RegisterPostInitializationOutput输出到用户编译上下文——既避免文件IO,又完整保留原文件的XML注释和格式。
步骤1:将枚举源文件设置为嵌入式资源
在生成器项目中找到ConfigFlags.cs文件,右键→属性:
- 把「生成操作」改为嵌入式资源
- 记录资源的完整名称(默认格式为
{项目命名空间}.{文件夹层级}.{文件名},例如项目命名空间是MyCodeGenerator,文件放在SharedEnums文件夹下,资源名就是MyCodeGenerator.SharedEnums.ConfigFlags.cs)
步骤2:在增量生成器中读取嵌入式资源
在生成器的初始化逻辑里,从当前程序集读取嵌入式资源的内容:
using System.IO; using System.Reflection; using Microsoft.CodeAnalysis; [Generator] public class MyIncrementalGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { // 读取嵌入式资源中的ConfigFlags源码 var assembly = Assembly.GetExecutingAssembly(); const string resourceName = "MyCodeGenerator.SharedEnums.ConfigFlags.cs"; using var stream = assembly.GetManifestResourceStream(resourceName); using var reader = new StreamReader(stream!); var configFlagsSource = reader.ReadToEnd(); // 通过RegisterPostInitializationOutput输出到编译上下文 context.RegisterPostInitializationOutput(ctx => { ctx.AddSource("ConfigFlags.g.cs", configFlagsSource); }); // 后续的生成器逻辑... } }
方案优势
- 合规性:完全规避文件IO,资源读取在内存中完成,符合Roslyn分析器/生成器的规则
- 完整性:原文件的XML注释、代码格式、枚举成员细节全部保留,不会像反射生成那样丢失信息
- 易维护:只需要在生成器项目中维护一份
ConfigFlags定义,输出给用户的版本完全一致,避免多源同步问题
注意事项
- 调试时可以用
Assembly.GetExecutingAssembly().GetManifestResourceNames()输出所有可用资源名,确认目标资源的名称是否正确 - 如果文件路径变动(比如移动到其他文件夹),要同步更新代码中的
resourceName - 确保生成器项目的目标框架与用户项目兼容,避免编译兼容性问题
内容的提问来源于stack exchange,提问作者monkey0506
相关产品推荐
相关产品推荐

