我们有一个非常大的解决方案(140个项目)我们将不同的项目部署到不同的服务器。完成部署的成本很高(按时间),因此我们将尝试跟踪我们的更改,以确定哪些项目受更改影响,然后仅部署这些项目。
例如:
假设我们有一个项目“Integral Part 1”(IP1)和另一个“Integral Part 2”(IP2)。在IP2内部,我们有一个类,广告,有一个生成html链接的方法,GenerateLink。 GenerateLink由广告中的另一个方法GenerateAd调用。我修改了GenerateLink。
IP1呼入并使用IP2中提供的服务。因此,需要重新部署IP1,以便在IP1中显示更改。
这是一个简单的观点,但应该将问题联系起来。目前,我需要进入GenerateLink方法并查找所有引用,然后按照每个引用查找它们的所有引用。我重复这个过程,直到找到解决方案中所有项目的所有引用,这些引用在某种程度上受到我的更改的影响。
是否有某种方法可以自动执行此过程,并简单地以递归方式请求方法的所有引用?
我在搜索中找到的最接近的答案是:Programmatically find all references to a function recursively,但我认为这不是我想要的。这听起来更像是Visual Studio中已经找到的所有引用工具。
答案 0 :(得分:5)
您可以使用Roslyn
aka 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....");
}
}
}
在运行示例之前下载并安装以下项目:
需要进行以下设置以避免MSBuildWorkspace
引发异常的运行时异常
The type or namespace name 'MSBuild' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?)
因为nuget包中的程序集是基于4.5.2构建的。
创建一个针对.Net 4.6的控制台应用程序并安装nuget包: Microsoft.CodeAnalysis 1.0.0
上述代码的测试运行:
ReferenceFinder finder = new ReferenceFinder();
finder.Find("Read");
输出:
此程序可能需要更多增强,因为Roslyn
更强大。但这应该会给你一个良好的开端。您可以浏览有关Roslyn
的更多信息,并且可以从C#代码中完全控制项目解决方案代码等。
TODO:我将为这个控制台应用创建一个github项目,我很快就会更新这篇文章。