如何在C# Analyzer中获取Operation调用的实例类型?
解决方案
要解决这个问题,核心是从链式调用的语法结构中回溯到最外层实例节点,并正确转换为SyntaxNode来获取语义信息,具体步骤和修正代码如下:
关键问题分析
你之前的错误在于直接将SyntaxToken传入GetSymbolInfo,而该方法要求参数为SyntaxNode。此外,链式调用(如test.test2.ToArray())的语法结构是嵌套的MemberAccessExpression,不能直接通过GetFirstToken()拿到有效实例节点,需要逐层回溯。
修正后的Analyzer代码
private static void AnalyzeOperationAction(OperationAnalysisContext context) { // 过滤非方法调用的语法节点 if (context.Operation.Syntax is not InvocationSyntax invocationSyntax) return; // 回溯链式调用,定位最外层的实例表达式 var currentExpression = invocationSyntax.Expression; while (currentExpression is MemberAccessExpressionSyntax memberAccess) { currentExpression = memberAccess.Expression; } // 确认最外层是标识符节点(对应示例中的test) if (currentExpression is not IdentifierNameSyntax instanceIdentifier) return; // 获取实例的符号信息 var symbolInfo = context.SemanticModel.GetSymbolInfo(instanceIdentifier, context.CancellationToken); var localSymbol = symbolInfo.Symbol as ILocalSymbol; if (localSymbol == null) return; // 验证实例类型是否为TestClazz(需替换为你的命名空间) var instanceType = localSymbol.Type; if (instanceType.Name == nameof(TestClazz) && instanceType.ContainingNamespace.Name == "YourNamespace") { // 执行后续检查并生成诊断 var diagnostic = Diagnostic.Create( MissingInitCallDescriptor, invocationSyntax.GetLocation(), instanceType.Name); context.ReportDiagnostic(diagnostic); } }
核心要点说明
- 语法结构回溯:链式调用的本质是嵌套的
MemberAccessExpressionSyntax,通过循环获取memberAccess.Expression,最终得到最外层的实例标识符节点(如test对应的IdentifierNameSyntax)。 - Token转Node:如果需要从
SyntaxToken转换为SyntaxNode,可以直接调用token.Parent(比如你之前拿到的instance令牌,其Parent就是IdentifierNameSyntax),但从语法结构遍历的方式更可靠。 - 语义信息获取:通过
SemanticModel.GetSymbolInfo()获取实例符号,再通过ILocalSymbol.Type拿到实例的类型,进而验证是否为目标类型TestClazz。
内容的提问来源于stack exchange,提问作者dognose
相关产品推荐
相关产品推荐

