我正在尝试编写一个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()));
}
答案 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
。但是,如果您要积累所有变量修改等信息,就可以自己做。