[英]C# Recursively Find References in All Projects In Solution
我們有一個非常大的解決方案(140個項目),我們將不同的項目部署到不同的服務器上。 進行完整的部署是昂貴的(按時),因此,我們將嘗試跟蹤更改以確定哪些項目受更改影響,然后僅部署這些項目。
例如:
假設我們有一個項目“集成部分1”(IP1)和另一個“集成部分2”(IP2)。 在IP2內,我們有一個Advert類,它帶有一個生成html鏈接的方法GenerateLink。 AdvertLink由廣告中的另一個方法GenerateAd調用。 我修改了GenerateLink。
IP1呼叫並使用IP2中可用的服務。 因此,將需要重新部署IP1,以使更改在IP1中可見。
這是一個簡單的視圖,但應與問題相關。 當前,我需要進入GenerateLink方法並找到所有引用,然后跟隨每個引用並找到它們上的所有引用。 我重復此過程,直到找到解決方案中所有項目的所有引用,這些引用以某種方式受到我的更改的影響。
是否有某種方法可以自動執行此過程,並簡單地遞歸地要求所有方法的引用?
我在搜索中找到的最接近的答案是:以編程方式遞歸地找到對函數的所有引用 ,但是我認為這並不是我要找的東西。 這聽起來更像是Visual Studio中已經存在的“查找所有引用”工具。
您可以使用Roslyn
(也稱為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
引發異常,需要以下設置,因為nuget程序包中的程序集是內置的, MSBuildWorkspace
The type or namespace name 'MSBuild' does not exist in the namespace 'Microsoft.CodeAnalysis' (are you missing an assembly reference?)
在4.5.2。
創建一個針對.Net 4.6的控制台應用程序並安裝nuget包: Microsoft.CodeAnalysis 1.0.0
上面代碼的測試運行:
ReferenceFinder finder = new ReferenceFinder();
finder.Find("Read");
輸出:
由於Roslyn
功能更強大,因此該程序可能需要更多增強。 但這應該為您提供一個開端。 您可以探索有關Roslyn
更多信息,並且可以從C#代碼完全控制項目解決方案代碼等。
待辦事項:我將為此控制台應用程序創建一個github項目,我將盡快更新此帖子。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.