在解决方案中使用Roslyn检索所有类型

use*_*817 3 c# roslyn

有谁知道如何检索解决方案中的所有可用类型(语义)?从多个项目中创建汇编很容易。

MSBuildWorkspace workspace = MSBuildWorkspace.Create();
var solution = await workspace.OpenSolutionAsync(solutionPath, cancellationToken);
var compilations = await Task.WhenAll(solution.Projects.Select(x => x.GetCompilationAsync(cancellationToken)));
Run Code Online (Sandbox Code Playgroud)

仅迭代所有ClassDeclarations对我来说是不够的,因为我想要所有类型以及它们之间的连接。

foreach (var tree in compilation.SyntaxTrees)
{
    var source = tree.GetRoot(cancellationToken).DescendantNodes();
    var classDeclarations = source.OfType<ClassDeclarationSyntax>();
}
Run Code Online (Sandbox Code Playgroud)

Tam*_*mas 5

对于给定的编译,你可以通过到达所有可用的类型Compilation.GlobalNamespace通过遍历所有GetTypeMembers()GetNamespaceMembers()递归。这并没有为您提供解决方案中的所有类型,而是为您提供了当前编译(项目)通过其所有引用均可使用的所有类型。

为了不重新发明轮子,它是:

IEnumerable<INamedTypeSymbol> GetAllTypes(Compilation compilation) =>
    GetAllTypes(compilation.GlobalNamespace);

IEnumerable<INamedTypeSymbol> GetAllTypes(INamespaceSymbol @namespace)
{
    foreach (var type in @namespace.GetTypeMembers())
        foreach (var nestedType in GetNestedTypes(type))
            yield return nestedType;

    foreach (var nestedNamespace in @namespace.GetNamespaceMembers())
        foreach (var type in GetAllTypes(nestedNamespace))
            yield return type;
}

IEnumerable<INamedTypeSymbol> GetNestedTypes(INamedTypeSymbol type)
{
    yield return type;
    foreach (var nestedType in type.GetTypeMembers()
        .SelectMany(nestedType => GetNestedTypes(nestedType)))
        yield return nestedType;
}
Run Code Online (Sandbox Code Playgroud)

  • 我编辑了你的答案,而不是发布一个新的答案,因为这个想法无疑是你的,但可能需要实施。 (2认同)