Roslyn 在解决方案中的所有项目中查找对方法的所有引用

jra*_*ser 5 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(); 
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

public static void GetPersonOutsideReference()
{
    var c = new Class1();
    c.GetPerson(Guid.NewGuid());
} 
Run Code Online (Sandbox Code Playgroud)

我希望 Find2 方法末尾的计数返回 2,类中的引用为 1,另一个项目中的引用为 1,但它始终为 1。

我尝试了几种方法,包括其他 SO Posts: 1 , 2 , 3,但都没有成功。

jra*_*ser 3

我找到了一种似乎是正确的方法。我还没有看到一个解决方案或答案可以为您提供解决方案中的所有参考资料。

您首先要在项目中查询该方法所属的类型(类)。正如我在问题中提到的,尽管多个项目可能引用并使用它们相同的类型,但它们没有该类型的相同符号。因此,您需要做的是通过向每个编译传递一个 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");
Run Code Online (Sandbox Code Playgroud)

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

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

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