我们有一个非常大的解决方案(140个项目),我们将不同的项目部署到不同的服务器上。进行完整的部署是昂贵的(按时),因此,我们将尝试跟踪更改以确定哪些项目受更改影响,然后仅部署这些项目。
例如:
假设我们有一个项目“集成部分1”(IP1)和另一个“集成部分2”(IP2)。在IP2内,我们有一个Advert类,它带有一个生成html链接的方法GenerateLink。AdvertLink由广告中的另一个方法GenerateAd调用。我修改了GenerateLink。
IP1呼叫并使用IP2中可用的服务。因此,将需要重新部署IP1,以使更改在IP1中可见。
这是一个简单的视图,但应与问题相关。当前,我需要进入GenerateLink方法并找到所有引用,然后跟随每个引用并找到它们上的所有引用。我重复此过程,直到找到解决方案中所有项目的所有引用,这些引用以某种方式受到我的更改的影响。
是否有某种方法可以自动执行此过程,并简单地递归地要求所有方法的引用?
我在搜索中找到的最接近的答案是:以编程方式递归地找到对函数的所有引用,但是我认为这并不是我要找的东西。这听起来更像是Visual Studio中已经存在的“查找所有引用”工具。
您可以使用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)
在运行示例之前,请下载并安装以下项目:
由于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项目,我将尽快更新此帖子。