You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 12:03:03