Roslyn在求解中查找所有项目中方法的所有引用

时间:2018-03-14 16:23:03

标签: c# roslyn

我一直试图在整个解决方案中找到对方法的所有引用。有人会认为SymbolFinder.FindReferencesAsync将ISymbol作为参数进行搜索,而解决方案对象会这样做,但它不会...

所有文章和SO问题/答案似乎都指出它是解决方案。它适用于查找包含它的程序集内的方法的所有引用,但不适用于引用它的任何项目。我有一个理论认为,这是因为当您创建引用时,方法的符号在引用程序集中是不同的,并且它们希望您获取该符号,然后使用SymbolFinder.FindSourceDeclarationsAsync将其解析为您正在查找的实际符号对于。

如果是这样的话我真的不知道如何去做?也许以某种方式得到程序集中所有符号的列表,然后对每个人进行FindSource调用并比较它以查看它是否引用了您的MethodSymbol?我当然希望不会!

这是一个简单的例子

public void Find2()
{
    string solutionPath = @"C:\Projects\RoslynTestTargetProject\RoslynTestTargetProject.sln";
    var msWorkspace = MSBuildWorkspace.Create();
    var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
    var methodProjectComp = solution.Projects.Single(x => x.Name == "RoslynTestTargetProject").GetCompilationAsync().Result;

    // I have loaded these all kinds of different ways but it never impacts the end result
    var classWithMethodToSearchFor = methodProjectComp.GetTypeByMetadataName("RoslynTestTargetProject.Class1");
    var methodToSearchFor = classWithMethodToSearchFor.GetMembers("GetPerson").First() as IMethodSymbol;

    var references = SymbolFinder.FindReferencesAsync(methodToSearchFor, solution).Result;
    var callers = SymbolFinder.FindCallersAsync(methodToSearchFor, solution).Result;

    int c = references.Select(x => x.Locations.Count()).Sum(); 
}

这是我正在搜索的方法的类和一个对它的引用。

public class Class1
{
    public Class1() {}        
    public Person GetPerson(Guid id) => new Person();
    public IEnumerable<Person> GetPeople(IEnumerable<Guid> ids) => ids.Select(x => GetPerson(x));
}

对它的另一个引用只是一个简单的控制台项目,其中包含以下内容:

public static void GetPersonOutsideReference()
{
    var c = new Class1();
    c.GetPerson(Guid.NewGuid());
} 

我希望Find2方法结束时的计数为类中的引用返回2,1,而另一个项目中的引用返回1,但它始终为1.

我尝试过多种方法,包括其他SO帖子:123但没有成功。

1 个答案:

答案 0 :(得分:0)

我想出了一种方法,这似乎是正确的。我还没有看到解决方案或答案,它为您提供解决方案中的所有参考资料。

首先,您需要在项目中查询方法所属的类型(类)。正如我在我的问题中提到的那样,尽管多个项目可能引用和使用它们相同的类型,但它们对于该类型没有相同的符号。所以你需要做的是通过传递MetadataName来询问每个编译是否具有匹配的类型。

foreach (var project in solution.Projects)
{
     var compilation = project.GetCompilationAsync().Result;

      // Look for a reference to the Class in the Assembly
      var classRef = compilation.GetTypeByMetadataName("RoslynTestTargetProject.Class1");

如果引用不为null,则表示正在程序集中使用该类型。现在,您可以检查您对该编译特定方法的符号引用,如下所示:

//For Methods
var refs = SymbolFinder.FindReferencesAsync(mSymbol, solution).Result;

//For Constructors
var refs = classRef.Constructors.Select(m => SymbolFinder.FindReferencesAsync(m, solution).Result).ToList();