如何在C# Source Generator中从PropertyDeclarationSyntax获取属性数据类型
Source Generator读取属性类型名称的解决方案
你遇到的异常是因为直接读取语法节点
PropertyDeclarationSyntax.Type的字符串表现,没有依赖语义模型解析类型信息。语法节点仅存储代码结构,遇到别名、未绑定类型、泛型等场景时,直接调用ToString会触发异常,也无法获取到int/string等C#内置类型的别名,只会返回System.Int32/System.String这类完整名称。
具体改造方案
- 第一步:传递语义模型到属性处理逻辑
你需要把Execute方法中获取到的SemanticModel实例传递到AddProperty方法中,修改Execute内的属性遍历逻辑:
foreach (var member in dto.DescendantNodes()) { if (member is PropertyDeclarationSyntax property) { // 新增:获取当前语法树的语义模型 var semanticModel = context.Compilation.GetSemanticModel(dto.SyntaxTree); // 传递语义模型到AddProperty dataClass.AddProperty(property, semanticModel); } }
- 第二步:改写
AddProperty方法,通过语义符号获取类型名
修改AddProperty的方法签名与实现,通过TypeInfo获取类型符号,再通过指定显示格式拿到符合要求的类型名称:
public void AddProperty(PropertyDeclarationSyntax property, SemanticModel semanticModel) { // 从语义模型获取类型符号 var typeInfo = semanticModel.GetTypeInfo(property.Type); var typeSymbol = typeInfo.Type; if (typeSymbol == null) { // 异常兼容:无法解析类型时可以跳过或者输出诊断日志 return; } // 配置显示格式:使用C#内置类型别名,只显示类型名不包含命名空间 var displayFormat = new SymbolDisplayFormat( typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly, miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes); var typeName = typeSymbol.ToDisplayString(displayFormat); Properties.Add( new DataField { PropertyName = property.Identifier.ValueText, DataType = typeName, Size = GetPropertySize(compilation, property, typeName), WriteMethod = GetWriteMethod(typeName), ReadMethod = GetReadMethod(typeName), Offset = Size }); }
效果说明
上述方法可以正确输出你需要的类型名:
- 值类型
Int32会输出int - 引用类型
String会输出string - 布尔类型
Boolean会输出bool - 可空值类型
Nullable<Int32>会输出int? - 自定义类型会直接输出类名,不会携带命名空间前缀
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

