C#在解决方案中的所有项目中递归查找引用

Sai*_*ori 0 c# visual-studio

我们有一个非常大的解决方案(140个项目),我们将不同的项目部署到不同的服务器上。进行完整的部署是昂贵的(按时),因此,我们将尝试跟踪更改以确定哪些项目受更改影响,然后仅部署这些项目。

例如:

假设我们有一个项目“集成部分1”(IP1)和另一个“集成部分2”(IP2)。在IP2内,我们有一个Advert类,它带有一个生成html链接的方法GenerateLink。AdvertLink由广告中的另一个方法GenerateAd调用。我修改了GenerateLink。

IP1呼叫并使用IP2中可用的服务。因此,将需要重新部署IP1,以使更改在IP1中可见。

这是一个简单的视图,但应与问题相关。当前,我需要进入GenerateLink方法并找到所有引用,然后跟随每个引用并找到它们上的所有引用。我重复此过程,直到找到解决方案中所有项目的所有引用,这些引用以某种方式受到我的更改的影响。

是否有某种方法可以自动执行此过程,并简单地递归地要求所有方法的引用?

我在搜索中找到的最接近的答案是:以编程方式递归地找到对函数的所有引用,但是我认为这并不是我要找的东西。这听起来更像是Visual Studio中已经存在的“查找所有引用”工具。

ven*_*mit 6

您可以使用Roslynaka Microsoft.CodeAnalysis来实现这一目标。您需要设置机器才能正常工作。

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.Text;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RoslynCompiler
{
    class ReferenceFinder
    {
        public void Find(string methodName)
        {

            string solutionPath = @"C:\Users\...\ConsoleForEverything.sln";
            var msWorkspace = MSBuildWorkspace.Create();

            List<ReferencedSymbol> referencesToMethod = new List<ReferencedSymbol>();
            Console.WriteLine("Searching for method \"{0}\" reference in solution {1} ", methodName, Path.GetFileName(solutionPath));
            ISymbol methodSymbol = null;
            bool found = false;

            //You must install the MSBuild Tools or this line will throw an exception.

            var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
            foreach (var project in solution.Projects)
            {
                foreach (var document in project.Documents)
                {
                    var model = document.GetSemanticModelAsync().Result;

                    var methodInvocation = document.GetSyntaxRootAsync().Result;
                    InvocationExpressionSyntax node = null;
                    try
                    {
                        node = methodInvocation.DescendantNodes().OfType<InvocationExpressionSyntax>()
                         .Where(x => ((MemberAccessExpressionSyntax)x.Expression).Name.ToString() == methodName).FirstOrDefault();

                        if (node == null)
                            continue;
                    }
                    catch(Exception exception)
                    {
                        // Swallow the exception of type cast. 
                        // Could be avoided by a better filtering on above linq.
                        continue;
                    }

                    methodSymbol = model.GetSymbolInfo(node).Symbol;
                    found = true;
                    break;
                }

                if (found) break;
            }

            foreach (var item in SymbolFinder.FindReferencesAsync(methodSymbol, solution).Result)
            {
                foreach (var location in item.Locations)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Project Assembly -> {0}", location.Document.Project.AssemblyName);
                    Console.ResetColor();
                }

            }

            Console.WriteLine("Finished searching. Press any key to continue....");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在运行示例之前,请下载并安装以下项目:

.NET 4.6运行时

.NET 4.6目标包

MSBuildTools 2015

由于nuget包中的程序集建立在4.5.2上,因此需要以下设置以避免运行时MSBuildWorkspace引发Throws异常 The type or namespace name 'MSBuild' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?)

创建一个针对.Net 4.6的控制台应用程序并安装nuget包: Microsoft.CodeAnalysis 1.0.0

上面代码的测试运行:

        ReferenceFinder finder = new ReferenceFinder();
        finder.Find("Read");
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明

这个程序可能需要更多的增强,因为Roslyn它的功能要强大得多。但这应该为您提供一个开端。您可以探索更多信息,Roslyn并且可以从C#代码完全控制您的项目解决方案代码等。

待办事项:我将为此控制台应用程序创建一个github项目,我将尽快更新此帖子。