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

如何用Roslyn解析C#类的公共方法名及方法体内的方法调用

使用Roslyn提取C#类的公共方法及方法体内的调用

既然你已经能借助Roslyn拿到类中的公共方法名,那要提取方法体内的方法/API调用,核心是利用Roslyn的语法遍历器(CSharpSyntaxWalker)深入方法体的语法节点,识别出所有的方法调用表达式(InvocationExpressionSyntax)。下面是具体的实现步骤和示例代码:

1. 准备依赖

首先确保你的项目已经安装了Roslyn的核心NuGet包:

  • Microsoft.CodeAnalysis
  • Microsoft.CodeAnalysis.CSharp

2. 核心思路

  1. 先将目标C#代码解析为SyntaxTree,定位到目标类的语法节点;
  2. 筛选出类中的所有公共方法声明;
  3. 对每个方法的方法体,使用自定义的SyntaxWalker遍历节点,捕获所有方法调用。

3. 完整实现代码

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.Linq;

public class MethodCallCollector : CSharpSyntaxWalker
{
    // 存储收集到的方法调用名称
    public List<string> MethodCalls { get; } = new List<string>();

    public override void VisitInvocationExpression(InvocationExpressionSyntax node)
    {
        base.VisitInvocationExpression(node);

        // 提取方法调用的名称
        string methodName = GetMethodCallName(node);
        if (!string.IsNullOrEmpty(methodName))
        {
            MethodCalls.Add(methodName);
        }
    }

    private string GetMethodCallName(InvocationExpressionSyntax invocation)
    {
        // 处理两种常见调用场景:成员访问调用、直接标识符调用
        if (invocation.Expression is MemberAccessExpressionSyntax memberAccess)
        {
            return memberAccess.Name.Identifier.ValueText;
        }
        else if (invocation.Expression is IdentifierNameSyntax identifierName)
        {
            return identifierName.Identifier.ValueText;
        }
        return null;
    }
}

public class RoslynAnalyzer
{
    public static void AnalyzePersonClass()
    {
        // 你的目标C#代码
        string code = @"
public class Person { 
    public string Name { get; private set; } 
    public Person(string name) { Name = name; } 
    public void Evaporate() { Console.WriteLine(""Hello World""); } 
    public string Speak() { string str = ""test""; return string.Format(""Hello! My name is {0}"", Name); } 
}";

        // 1. 解析代码为语法树
        SyntaxTree tree = CSharpSyntaxTree.ParseText(code);
        CompilationUnitSyntax root = tree.GetCompilationUnitRoot();

        // 2. 定位到Person类的节点
        ClassDeclarationSyntax personClass = root.DescendantNodes()
            .OfType<ClassDeclarationSyntax>()
            .First(c => c.Identifier.ValueText == "Person");

        // 3. 筛选所有公共方法
        IEnumerable<MethodDeclarationSyntax> publicMethods = personClass.Members
            .OfType<MethodDeclarationSyntax>()
            .Where(m => m.Modifiers.Any(SyntaxKind.PublicKeyword));

        foreach (var method in publicMethods)
        {
            Console.WriteLine($"公共方法:{method.Identifier.ValueText}");

            // 4. 收集该方法体内的方法调用
            var collector = new MethodCallCollector();
            collector.Visit(method.Body);

            if (collector.MethodCalls.Any())
            {
                Console.WriteLine("  方法内调用:");
                foreach (var call in collector.MethodCalls.Distinct())
                {
                    Console.WriteLine($"    - {call}");
                }
            }
            Console.WriteLine();
        }
    }
}

4. 关键代码说明

  • MethodCallCollector:继承自CSharpSyntaxWalker,专门遍历并捕获方法调用节点。它处理两种常见调用形式:
    • 成员访问调用(比如Console.WriteLine):通过MemberAccessExpressionSyntax提取方法名;
    • 直接标识符调用(比如本地方法):通过IdentifierNameSyntax提取方法名。
  • RoslynAnalyzer:负责代码解析、类定位、公共方法筛选,并调用收集器获取每个方法内的调用信息。

5. 运行结果

针对你提供的Person类,运行后会输出:

公共方法:Evaporate
  方法内调用:
    - WriteLine

公共方法:Speak
  方法内调用:
    - Format

如果需要更完整的调用信息(比如包含类型名,如Console.WriteLine),可以修改GetMethodCallName方法,拼接类型前缀即可。

内容的提问来源于stack exchange,提问作者kawser-nerd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:25:37