如何使用ISyntaxReceiver获取ClassDeclarationSyntax含继承的所有成员方法
实现方案
仅通过ClassDeclarationSyntax的语法节点无法获取继承成员,因为语法树仅存储单文件的语法结构,不包含继承链、跨程序集引用等元数据信息,必须结合**语义模型(SemanticModel)**和符号体系实现。
步骤1:调整SyntaxReceiver(仅修复潜在空引用问题,收集逻辑不变)
public class ControllerSyntaxReceiver : ISyntaxReceiver { // 初始化集合避免空引用异常 public List<ClassDeclarationSyntax> Candidates { get; } = new(); public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { if (syntaxNode is ClassDeclarationSyntax classDeclaration && classDeclaration.Identifier.ValueText.EndsWith("Controller")) { Candidates.Add(classDeclaration); } } }
步骤2:在生成器Execute方法中通过语义符号遍历继承链
核心逻辑为通过INamedTypeSymbol的BaseType属性递归遍历整个继承链,逐个拉取所有类的方法成员:
[Generator] public class ControllerGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { context.RegisterForSyntaxNotifications(() => new ControllerSyntaxReceiver()); } public void Execute(GeneratorExecutionContext context) { if (context.SyntaxReceiver is not ControllerSyntaxReceiver receiver) return; var compilation = context.Compilation; foreach (var controllerSyntax in receiver.Candidates) { // 获取当前类的语义符号 var semanticModel = compilation.GetSemanticModel(controllerSyntax.SyntaxTree); var classSymbol = semanticModel.GetDeclaredSymbol(controllerSyntax); if (classSymbol == null) continue; // 拿到包括继承的所有实例方法 var allMethods = GetAllInheritedMethods(classSymbol); // 后续的生成逻辑写在这里,allMethods就是你需要的完整方法集合 } } // 遍历继承链拉取所有普通实例方法的工具方法 private static IEnumerable<IMethodSymbol> GetAllInheritedMethods(INamedTypeSymbol typeSymbol) { var processedTypes = new HashSet<INamedTypeSymbol>(); var currentType = typeSymbol; while (currentType != null && processedTypes.Add(currentType)) { // 可选:如果不需要object类的方法,打开下面的注释 // if (currentType.SpecialType == SpecialType.System_Object) break; foreach (var method in currentType.GetMembers().OfType<IMethodSymbol>()) { // 过滤条件可根据需求调整: // MethodKind.Ordinary 排除构造函数、析构函数、属性访问器等特殊方法 // IsStatic == false 排除静态方法 // DeclaredAccessibility == Accessibility.Public 仅保留public方法 if (method.MethodKind == MethodKind.Ordinary && !method.IsStatic && method.DeclaredAccessibility == Accessibility.Public) { yield return method; } } currentType = currentType.BaseType; } } }
补充说明
你可以根据业务需求调整GetAllInheritedMethods里的过滤条件,比如是否包含静态方法、是否保留私有/保护成员、是否过滤object类的方法等。拿到的IMethodSymbol包含了方法的名称、返回值、参数列表、特性等所有元数据信息,完全满足源生成的开发需求。
内容的提问来源于stack exchange,提问作者Mário Gabriel
相关产品推荐
相关产品推荐

