Roslyn在解决方案中获取方法调用引用

时间:2018-02-02 13:35:14

标签: c# .net roslyn code-analysis

我使用.NET framework 4.6

创建了一个非常简单的解决方案,里面有两个项目

TestReference.Data.dll

DataRepository.cs

using System.Collections.Generic;
using System.Linq;

namespace TestReferences.Data
{
    public class DataRepository
    {
        public IEnumerable<string> GetProductNames()
        {
            return Enumerable.Repeat("Prod Name", 30);
        }

        public IEnumerable<int> GetProductIds()
        {
            return Enumerable.Range(12, 13);
        }
    }
}

ProductService.cs

using System.Collections.Generic;

namespace TestReferences.Data
{
    public class ProductService : IProductService
    {
        private readonly DataRepository dataRepository;

        public ProductService()
        {
            dataRepository = new DataRepository();
        }

        public IEnumerable<string> GetRecentProductNames()
        {
            return this.dataRepository.GetProductNames();
        }

        public IEnumerable<int> GetRecentProductIds()
        {
            return this.dataRepository.GetProductIds();
        }
    }
}

IProductService.cs

using System.Collections.Generic;

namespace TestReferences.Data
{
    public interface IProductService
    {
        IEnumerable<int> GetRecentProductIds();
        IEnumerable<string> GetRecentProductNames();
    }
}

TestReference.Web.dll

一个MVC项目,它引用了TestReference.Data.dll

HomeController.cs

using System.Web.Mvc;
using TestReferences.Data;

namespace TestReferences.Web.Controllers
{
    public class HomeController : Controller
    {
        IProductService productService;

        public HomeController()
        {
            this.productService = new ProductService();
        }

        public ActionResult Index()
        {
            this.productService.GetRecentProductIds();
            this.productService.GetRecentProductNames();

            return View();
        }

        public ActionResult About()
        {
            this.productService.GetRecentProductNames();

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
}

在该结构中,如果您打开ProductService.cs并将光标放在GetRecentProductNames上,然后按shift + F12它会在TestReference.Web中显示2个结果(代码镜头显示另外一个)界面,仅适用于企业版)。 我已经创建了另一个控制台应用程序来获得相同的引用。

public static void Main()
{
    MSBuildWorkspace ms =  MSBuildWorkspace.Create();
    Solution solution = ms.OpenSolutionAsync(@"D:\SampleApps\TestReferences\TestReferences.sln").Result;

    Document doc = solution
        .Projects
        .Where(p => p.Name == "TestReferences.Data")
        .SelectMany(p => p.Documents)
        .FirstOrDefault(d => d.Name == "ProductService.cs");

    if (doc == null)
    {
        throw new NullReferenceException("DOc");
    }

    SemanticModel model = doc.GetSemanticModelAsync().Result;

    List<MethodDeclarationSyntax> methodDeclarations = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<MethodDeclarationSyntax>().ToList();

    // Method declaration is GetRecentProductNames()
    MethodDeclarationSyntax m = methodDeclarations.First();

    ISymbol symbolInfo = model.GetDeclaredSymbol(m);

    IEnumerable<ReferencedSymbol> references = SymbolFinder.FindReferencesAsync(symbolInfo, doc.Project.Solution).Result;
}

我在references内收到两个项目,但其位置为0.

  

[0] | GetRecentProductNames,0 refs
  [1] | GetRecentProductNames,0 refs

这是我与Roslyn和Microsoft.CodeAnalysis的第一次接触。该库的版本是

<package id="Microsoft.CodeAnalysis" version="2.6.1" targetFramework="net46" />

2 个答案:

答案 0 :(得分:0)

GetDeclaredSymbol如果是声明语法节点,则返回关联的符号。这不是你想要的。

您应该使用GetSymbolInfo来获取有关语法节点的符号信息:

var symbolInfo = semanticModel.GetSymbolInfo(m);
var references = SymbolFinder.FindReferencesAsync(symbolInfo, doc.Project.Solution).Result;

答案 1 :(得分:0)

实际上我试图实现与Visual Studio 2017中嵌入的View Call Hierarchy相同的功能。只需右键单击方法。