Roslyn Analyzer-查找接口方法调用的当前具体实现

时间:2018-09-20 02:17:34

标签: c# roslyn abstract-syntax-tree analyzer roslyn-code-analysis

我正在尝试编写一个Roslyn分析器,该分析器可以从接口的特定实现中检测方法调用,但是在实现类型检测方面存在问题。

当我使用类型为具体实现的变量时,它正确地标识了方法,但是当我使用类型为接口的变量时,它不能正确识别方法。通常试图找出如何使用Roslyn Code Analysis Apis获取接口的基础实现的类型

这是要分析的示例代码。即使两者都使用Operate

中的具体实现,它也可以正确检测到第二个Operable方法调用,但不能检测到第一个方法调用
using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            IOperable ioperable = new Operable();
            ioperable.Operate();

            Operable operable = new Operable();
            operable.Operate();
        }
    }

    public interface IOperable
    {
        void Operate();
    }

    public class Operable : IOperable
    {
        public void Operate()
        {

        }
    }
}

这是我当前的消息来源:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzeInvocation, SyntaxKind.InvocationExpression);
}

private static void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
{
    var invocation = (InvocationExpressionSyntax)context.Node;

    var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
    if (memberAccess == null || !memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
    {
        return;
    }

    var ident = memberAccess.Name.Identifier;
    if (ident.ToString().ToLower() != "operate")
    {
        return;
    }

    var calledFromType = context.SemanticModel.GetTypeInfo(memberAccess.Expression).Type;
    if (calledFromType.MetadataName != "Operable")
    {
        return;
    }
    context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation()));
}

1 个答案:

答案 0 :(得分:0)

我会让您感到失望,但是Roslyn是静态分析器,默认情况下它无法检索类型,调用等的动态信息。

要实现这一目标,您需要在roslyn下实现自定义动态分析,该分析将调查对变量的所有赋值,参数的传递等,以确定它可以包含的所有有关对象(类型,方法等)的信息。代码中的当前时间。

在下面的示例中必须清楚:

#You can create a function and call it with the needed parameters like that:

function Use-Params {
param(
[String]$Variable1,
[String]$Variable2
)
    Write-Host "Variable1 value: $Variable1 "
    Write-Host "Variable2 value: $Variable2 "
}

Use-Params -Variable1 "Value 1" -Variable2 "Value 2"

#Or you just overwrite the variables in the script

function Use-Params {
param(
[String]$Variable1 = "Value 1",
[String]$Variable2 = "Value 2"
)
    Write-Host "Variable1 value: $Variable1 "
    Write-Host "Variable2 value: $Variable2 "
}

Use-Params

Roslyn可以获取有关变量public interface IOperable { void Operate(); } public class Operable : IOperable { ... } public class OperableOther : IOperable { ... } ... IOperable ioperable = new Operable(); ioperable.Operate(); // at this time will invoke Operable.Operate(); ioperable = new OperableOther(); ioperable.Operate(); // at this time will OperableOther.Operate(); ioperable的编译时间信息,但不能认为它会从第一个赋值IOperable到第二个赋值Operable 。但是,如果您要积累所有变量修改等信息,就可以自己做。