如何用Roslyn解析C#类的公共方法名及方法体内的方法调用
使用Roslyn提取C#类的公共方法及方法体内的调用
既然你已经能借助Roslyn拿到类中的公共方法名,那要提取方法体内的方法/API调用,核心是利用Roslyn的语法遍历器(CSharpSyntaxWalker)深入方法体的语法节点,识别出所有的方法调用表达式(InvocationExpressionSyntax)。下面是具体的实现步骤和示例代码:
1. 准备依赖
首先确保你的项目已经安装了Roslyn的核心NuGet包:
Microsoft.CodeAnalysisMicrosoft.CodeAnalysis.CSharp
2. 核心思路
- 先将目标C#代码解析为
SyntaxTree,定位到目标类的语法节点; - 筛选出类中的所有公共方法声明;
- 对每个方法的方法体,使用自定义的
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
相关产品推荐
相关产品推荐

