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

C# 在解决方案中使用Roslyn检索所有类型,c#,roslyn,C#,Roslyn,有人知道如何检索解决方案中的所有可用类型(语义)吗? 从几个项目中创建编译是很容易的 MSBuildWorkspace workspace = MSBuildWorkspace.Create(); var solution = await workspace.OpenSolutionAsync(solutionPath, cancellationToken); var compilations = await Task.WhenAll(solution.Projects.Select(x =&g

有人知道如何检索解决方案中的所有可用类型(语义)吗? 从几个项目中创建编译是很容易的

MSBuildWorkspace workspace = MSBuildWorkspace.Create();
var solution = await workspace.OpenSolutionAsync(solutionPath, cancellationToken);
var compilations = await Task.WhenAll(solution.Projects.Select(x => x.GetCompilationAsync(cancellationToken)));
对我来说,仅仅迭代所有类声明是不够的,因为我需要所有类型以及它们之间的连接

foreach (var tree in compilation.SyntaxTrees)
{
    var source = tree.GetRoot(cancellationToken).DescendantNodes();
    var classDeclarations = source.OfType<ClassDeclarationSyntax>();
}
foreach(编译中的var-tree.SyntaxTrees)
{
var source=tree.GetRoot(cancellationToken.genderantNodes();
var classDeclarations=source.OfType();
}

对于给定的编译,您可以通过递归迭代所有
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;
}
IEnumerable GetAllTypes(编译)=>
GetAllTypes(compilation.GlobalNamespace);
IEnumerable GetAllTypes(InNamespaceSymbol@namespace)
{
foreach(变量类型在@namespace.GetTypeMembers()中)
foreach(GetNestedTypes(type)中的var nestedType)
收益嵌套型;
foreach(在@namespace.getnamespacembers()中的var nestedNamespace)
foreach(GetAllTypes(nestedNamespace)中的变量类型)
收益型;
}
IEnumerable GetNestedTypes(INamedTypeSymbol类型)
{
收益型;
foreach(type.GetTypeMembers()中的变量nestedType)
.SelectMany(nestedType=>GetnestedType(nestedType)))
收益嵌套型;
}
List ls=new List();
foreach(p.文件中的文件d)
{
SemanticModel m=d.GetSemanticModelAsync().Result;
List lc=d.GetSyntaxRootAsync().Result.degenantNodes().OfType().ToList();
foreach(信用证中的var c)
{
ISymbol s=m.GetDeclaredSymbol(c);
ls.加入(s);
}
}

一旦您可以访问解决方案,它就是:

IEnumerable<INamedTypeSymbol> types =
    solution
    .Projects
    .SelectMany(project => project.Documents)
    .Select(document =>
        new
        {
            Model = document.GetSemanticModelAsync().Result,
            Declarations = document.GetSyntaxRootAsync().Result
                .DescendantNodes().OfType<TypeDeclarationSyntax>()
        })
    .SelectMany(pair =>
        pair.Declarations.Select(declaration =>
            pair.Model.GetDeclaredSymbol(declaration) as INamedTypeSymbol));
IEnumerable类型=
解决方案
.项目
.SelectMany(project=>project.Documents)
.选择(文档=>
新的
{
Model=document.GetSemanticModelAsync().Result,
声明=document.GetSyntaxRootAsync().Result
.DegenantNodes()类型()的
})
.SelectMany(成对=>
pair.Declarations.Select(声明=>
pair.Model.GetDeclaredSymbol(声明)为INamedTypeSymbol);

我编辑了您的答案,而不是发布新答案,因为这个想法无疑是您的,但您可能需要实现。有一种方法可以只获取在解决方案中声明的类型。看,我可能错过了一些东西,但是运行这个我得到了所有的外部类型。没什么大不了的,只是不是我所期望的。
IEnumerable<INamedTypeSymbol> types =
    solution
    .Projects
    .SelectMany(project => project.Documents)
    .Select(document =>
        new
        {
            Model = document.GetSemanticModelAsync().Result,
            Declarations = document.GetSyntaxRootAsync().Result
                .DescendantNodes().OfType<TypeDeclarationSyntax>()
        })
    .SelectMany(pair =>
        pair.Declarations.Select(declaration =>
            pair.Model.GetDeclaredSymbol(declaration) as INamedTypeSymbol));