修复AutoSaveGenerator生成partial类时的重复属性编译错误
我通过实现IIncrementalGenerator编写了AutoSaveGenerator源生成器,用于为标记了[AutoSave]特性的partial类生成包含私有字段、OnPropertyChanged触发及Save调用逻辑的属性实现。
原类代码如下:
[AutoSave] public partial class GeneratedConfig : NotifiyingJsonSettings, IVersionable { [EnforcedVersion("1.0.0.0")] public Version Version { get; set; } = new Version(1, 0, 0, 0); public override string FileName { get; set; } = $"{AppContext.BaseDirectory}GeneratedConfig.json"; public virtual string TestString { get; set; } public virtual bool TestBool { get; set; } }
编译时出现重复属性定义错误:
The type 'GeneratedConfig' already contains a definition for 'FileName'
The type 'GeneratedConfig' already contains a definition for 'Version'
The type 'GeneratedConfig' already contains a definition for 'TestBool'
The type 'GeneratedConfig' already contains a definition for 'TestString'
生成器核心代码如下:
[Generator] public class AutoSaveGenerator : IIncrementalGenerator { // 完整实现代码见原问题 }
修复方案
1. 调整原类属性为partial声明
原类中已写了完整的get;set;属性定义,生成器又重复生成了同名属性,导致冲突。可以把原类中的属性改为partial修饰的仅签名形式,让生成器负责实现具体逻辑:
[AutoSave] public partial class GeneratedConfig : NotifiyingJsonSettings, IVersionable { [EnforcedVersion("1.0.0.0")] public partial Version Version { get; set; } public override partial string FileName { get; set; } public partial string TestString { get; set; } public partial bool TestBool { get; set; } }
同时修改生成器逻辑,仅识别带有partial修饰符的属性,生成对应的私有字段、OnPropertyChanged触发及Save调用逻辑。
2. 在生成器中过滤已有实现的属性
在生成器的语法分析阶段,添加判断逻辑,跳过已有完整访问器实现的属性:
// 伪代码,适配实际语法树API foreach (var property in classSymbol.GetMembers().OfType<IPropertySymbol>()) { // 检查属性是否无自定义访问器实现,或为partial属性 if (property.IsPartial || (!property.GetMethod.IsImplemented && !property.SetMethod.IsImplemented)) { // 生成带逻辑的属性实现代码 } }
这样生成器只会处理没有完整实现的属性,避免和原类中已有的属性定义冲突。
3. 改用字段作为生成依据(可选)
如果允许调整原类结构,可以只在原类中定义私有字段,由生成器生成对应的公共属性:
[AutoSave] public partial class GeneratedConfig : NotifiyingJsonSettings, IVersionable { [EnforcedVersion("1.0.0.0")] private Version _version = new Version(1, 0, 0, 0); private string _fileName = $"{AppContext.BaseDirectory}GeneratedConfig.json"; private string _testString; private bool _testBool; }
生成器根据这些私有字段,自动生成包含OnPropertyChanged和Save逻辑的公共属性,彻底避免重复定义问题。
内容的提问来源于stack exchange,提问作者Alexa

