如何在方法调用时查找方法参数的类型?

How to find the types of method arguments upon method call?

假设我们有以下基本模型:

public class Base
{
   ...
}

并且有M1, ..., Mn 模型来源于此。

我们有一个具有以下结构的接口:

public interface IExampleInterface
{
    void DoSomething(Base input);
}

假设我们对此有一个简单的实现 class,例如:

public class Example : IExampleInterface
{
   void DoSomething(Base input) 
   {
       System.Console.WriteLine("Please help me!!");
   }
}

IExampleInterface.DoSomething 方法在整个解决方案中使用不同的输入参数进行多次调用。

var ex = new Example();
var m = new M();
ex.DoSometing(m);

其中 M 可以是来自 M1, ..., Mn[=48= 的任何类型].

我设法从语法树中找到了接口,它的实现和参数类型,甚至我找到了调用者,但是我在[=33=中找不到传递参数的类型]IExampleInterface.DoSomething来电。

代码如下:

var interfaceName = "IExampleInterface";
var returnType = "Void";
var methodName = "DoSomething";
var arg = "Base";

var exInterface = compilations
        .SelectMany(compilation => compilation.SyntaxTrees.Select(syntaxTree => compilation.GetSemanticModel(syntaxTree)))
        .SelectMany(
            semanticModel => semanticModel
                .SyntaxTree
                .GetRoot()
                .DescendantNodes()
                .OfType<InterfaceDeclarationSyntax>()
                .Select(interfaceDeclarationSyntax => semanticModel.GetDeclaredSymbol(interfaceDeclarationSyntax)))
        .Where(s => s.Name == interfaceName)
        .FirstOrDefault();

var implementations = await SymbolFinder.FindImplementationsAsync(exInterface, solution);
var implementation = implementations.FirstOrDefault() as ITypeSymbol;
var method = exInterface
        .GetMembers(methodName)
        .Where(m => m.Kind == SymbolKind.Method)
        .Cast<IMethodSymbol>()
        .FirstOrDefault(m =>
            m.Parameters != null &&
            m.Parameters.Length == 1 &&
            m.Parameters[0].Type.Name == arg &&
            m.ReturnType.Name == returnType);

var callers = await SymbolFinder.FindCallersAsync(method, solution);

此时我卡住了。我对 Roslyn 比较陌生。我的问题是如何找到传递给 IExampleInterface.DoSomething 调用的参数类型?

我实际上通过获取编译的语义模型解决了这个问题。

首先,在找到所有调用者之后,我们需要在 [=19 的帮助下找到 InvocationExpression 节点=]CallingSymbol 来自 SymbolCallerInfo.

其次,我们必须从ArgumentList 属性 of [中得到我们感兴趣的参数InvocationExpression.

假设 arg 是所需的参数并且 compilationarg 来自的编译实例。

var type = compilation
      .GetSemanticModel(arg.SyntaxTree)
      .GetTypeInfo(arg.ChildNodes().First());