我想在我的解决方案中找到所有PropertyChangedEventHandler
个事件,然后找到添加到这些事件的所有侦听器。但我似乎无法获得事件列表。
这是所分析解决方案中的所有代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RoslynTarget
{
public class Example : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
public void DoNothing() { }
}
}
这是我分析它的代码。 references.Count == 1
和r.Locations.Count == 0
,但应找到一个位置。这里发生了什么?
Program.cs的
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.MSBuild;
namespace RoslynTest
{
class Program
{
static void Main(string[] args)
{
const string solutionPath = @"C:\Users\<user>\Code\RoslynTarget\RoslynTarget.sln";
const string projectName = "RoslynTarget";
var msWorkspace = MSBuildWorkspace.Create(new Dictionary<string, string> { { "CheckForSystemRuntimeDependency", "true" } });
var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result;
var project =
solution.Projects
.Where(proj => proj.Name == projectName)
.First();
var compilation = project.GetCompilationAsync().Result;
var eventType = compilation.ResolveType("System.ComponentModel.PropertyChangedEventHandler").First();
var references = SymbolFinder.FindReferencesAsync(eventType, solution).Result;
foreach (var r in references)
{
foreach (var loc in r.Locations)
{
// ...
}
}
}
}
}
Extensions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
namespace RoslynTest
{
public static class Extensions
{
public static IEnumerable<INamedTypeSymbol> ResolveType(this Compilation compilation, string classFullName)
{
return new IAssemblySymbol[] { compilation.Assembly }
.Concat(compilation.References
.Select(compilation.GetAssemblyOrModuleSymbol)
.OfType<IAssemblySymbol>())
.Select(asm => asm.GetTypeByMetadataName(classFullName))
.Where(cls => cls != null);
}
}
}
答案 0 :(得分:5)
最近我做了类似的事情,我试图在完整的解决方案中找到方法的参考。
要使用FindReferenceAsync
,您首先要创建语义模型,然后从那里找到符号。获得符号后,您可以使用FindReferenceAsync
。
这是我使用过的代码片段,它起作用了:
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();
}
}
这里是complete working code。如果您想要显示Roslyn树,那么您可以尝试使用Roslyn tree visualizer来查看代码结构。
根据OP安装Roslyn SDK的评论中的讨论解决了这个问题。假设在使用GetCompilationAsync
时,与Nuget dll相比,SDK中可能会有一些更新来生成符号信息。