我正在尝试编写一个Roslyn分析器来检测在数组上调用Enumerable.Count()
的用法。以下是我的分析器中的相关代码:
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeInvocationExpression, SyntaxKind.InvocationExpression);
}
private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
if (!memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
{
return;
}
Debug.Assert(memberAccess != null);
var ident = memberAccess.Name.Identifier;
// Check whether the method is Count() and there is no parameter list before we try to use the Symbol APIs.
if (ident.ToString() != nameof(Enumerable.Count))
{
return;
}
var arguments = invocation.ArgumentList.Arguments;
if (arguments.Count > 0)
{
return;
}
// Make sure that the subject is an array.
var subject = memberAccess.Expression;
var subjectSymbol = context.SemanticModel.GetSymbolInfo(subject).Symbol;
if (subjectSymbol == null)
{
return;
}
// ???
}
我试图确定调用Count()
的对象是否是一个数组。我稍微扫描了一下API,我发现ILocalSymbol
有一个Type
属性,还有一个IFieldSymbol
属性Type
,这两个属性都可能会让你获得类型对象。但是,我不知道我正在分析的对象是方法调用/ etc的本地/字段/结果,所以我希望IFieldSymbol
和ILocalSymbol
例如共享一些公共基础接口,比如说IVariableSymbol
,它为您提供Type
,而不必知道变量可能来自的所有可能位置。但是,似乎两个接口都直接来自ISymbol
。
最好的解决方案是做这样的事情吗?
internal static class SymbolUtilities
{
public static ITypeSymbol GetType(ISymbol symbol)
{
if (symbol is IFieldSymbol)
{
return ((IFieldSymbol)symbol).Type;
}
if (symbol is ILocalSymbol)
{
return ((ILocalSymbol)symbol).Type;
}
...
}
}
答案 0 :(得分:2)
您可以使用GetTypeInfo
类的SemanticModel
方法获取有关类型的信息:
ITypeSymbol subjectType = context.SemanticModel.GetTypeInfo(subject).Type;
您可以在文章
中找到有关它的更多详细信息" Introduction to Roslyn and its use in program development"