如何使用C# Source Generator获取类成员的编译期默认值
C# 9 Source Generator 获取属性默认值方案
你需要结合Roslyn的语法解析能力+语义模型来提取属性的初始化默认值,这类默认值属于语法树中的赋值子节点,具体实现步骤如下:
- 第一步:在Generator中通过语法接收器筛选所有带初始化逻辑的属性声明节点,或者直接遍历语法树定位到目标
PropertyDeclarationSyntax节点 - 第二步:检查属性节点是否包含
EqualsValueClause,也就是= 1对应的语法节点,不存在则说明该属性没有设置默认值 - 第三步:通过
SemanticModel的GetConstantValue方法计算该赋值表达式的编译期常量值,就能拿到你需要的默认值
完整实现示例如下:
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; [Generator] public class DefaultValueExtractGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { // 注册语法接收器,预筛选符合条件的属性节点 context.RegisterForSyntaxNotifications(() => new PropertySyntaxReceiver()); } public void Execute(GeneratorExecutionContext context) { if (context.SyntaxReceiver is not PropertySyntaxReceiver receiver) return; foreach (var property in receiver.TargetProperties) { var semanticModel = context.Compilation.GetSemanticModel(property.SyntaxTree); // 读取属性的默认值赋值节点 if (property.Initializer is EqualsValueClauseSyntax valueClause) { // 计算编译期常量值 var constantResult = semanticModel.GetConstantValue(valueClause.Value); if (constantResult.HasValue) { // 此处拿到的就是你需要的默认值,示例场景下取值为1 object defaultValue = constantResult.Value; // 后续自行处理拿到的默认值即可 } } } } // 自定义语法接收器,提前收集所有带初始化逻辑的属性 private class PropertySyntaxReceiver : ISyntaxReceiver { public List<PropertyDeclarationSyntax> TargetProperties { get; } = new(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { if (syntaxNode is PropertyDeclarationSyntax { Initializer: not null } property) { TargetProperties.Add(property); } } } }
注意:该方法只能获取编译期可确定的常量默认值,如果默认值是运行时计算的表达式(比如
= DateTime.Now、= new CustomClass()),GetConstantValue会返回无值状态,这类场景需要你自行解析表达式节点生成对应的实现逻辑。
内容的提问来源于stack exchange,提问作者Lin Lee
相关产品推荐
相关产品推荐

