我需要获取给定项目的类之间的某种依赖关系图,即特定类使用的所有类。我想知道给定类正在使用哪些类,以便以后可以在项目中找到它们的文件路径。考虑以下简单示例:
public class Dog: Animal, IBark
{
public void Bark()
{
// Code to bark.
}
public void Fight(Cat cat)
{
// Code to fight cat.
}
}
对于此特定示例,我想知道Dog
类使用哪些类。因此,我想以编程方式访问具有那些依赖关系的对象。在这种情况下,该对象将包含IBark
,Animal
和Cat
类/接口,并可能包含它们各自的文件路径。
这在C#中可能吗?我尝试研究Roslyn API,尽管我可以解析文档并遍历它以找到节点,但是我还没有找到一种方法来获取与那些节点相关的元数据,这些元数据可能会给我我想要的内容(例如文件路径) 。这让我想知道是否没有更好的方法解决这个问题。
答案 0 :(得分:1)
这可以使用Roslyn
API来完成。算法如下:
semantic model
SyntaxTree
并遍历所有SyntaxNode
SyntaxNode
具体类型。如果检测到的语法是类定义(例如,Dog),请继续遍历,考虑到进一步检测到的类或接口取决于Dog 下面的示例代码。我也在github中提交了此内容。您将对sample unit tests和sample solution based on your example感兴趣。我假设单个文件仅包含一个类定义,但是我认为这足以让您开始。
var dependencies = new Dictionary<string, List<string>>();
//key - class name, value - list of dependent class names
var project = workspace.CurrentSolution.Projects.First();
foreach (var document in project.Documents)
{
var semanticModel = await document.GetSemanticModelAsync();
KeyValuePair<string, List<string>>? keyValue = null;
foreach (var item in semanticModel.SyntaxTree.GetRoot().DescendantNodes())
{
switch (item)
{
case ClassDeclarationSyntax classDeclaration:
case InterfaceDeclarationSyntax interfaceDeclaration:
if (!keyValue.HasValue)
{
keyValue = new KeyValuePair<string, List<string>>(semanticModel.GetDeclaredSymbol(item).Name, new List<string>());
}
break;
case SimpleBaseTypeSyntax simpleBaseTypeSyntax:
keyValue?.Value.Add(simpleBaseTypeSyntax.Type.ToString());
break;
case ParameterSyntax parameterSyntax:
keyValue?.Value.Add(parameterSyntax.Type.ToString());
break;
}
}
if (keyValue.HasValue)
{
dependencies.Add(keyValue.Value.Key, keyValue.Value.Value);
}
}
对于以上代码,工作空间的加载方式如下:
var workspace = MSBuildWorkspace.Create();
await workspace.OpenSolutionAsync(solutionFilePath);