Roslyn,如何获取所有类

8

如何从 Roslyn 编译中获取所有类?

var sln = Path.Combine(path, "xxx.sln");

var workspace   = MSBuildWorkspace.Create();
var solution    = await workspace.OpenSolutionAsync(sln);
var project     = solution.Projects.First(x => x.Name == "bbb");
var compilation = await project.GetCompilationAsync();
3个回答

11

这是我如何访问解决方案中的所有类。

class ClassVirtualizationVisitor : CSharpSyntaxRewriter
{   
    List<string> classes = new List<String>();
    
    public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        node = (ClassDeclarationSyntax) base.VisitClassDeclaration(node);
    
        string className = node.Identifier.ValueText;
        classes.Add(className); // save your visited classes
                
        return node;
    }
}

现在使用已访问的类:

var classVisitor = new ClassVirtualizationVisitor();
classVisitor.Visit(semanticModel.SyntaxTree.GetRoot());
    
var classes = classVisitor.classes; // list of classes in your solution

2
语义模型缺少定义,应该在哪里或如何初始化? - jimjim

6

这是我的工作代码:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    using Microsoft.CodeAnalysis.CSharp.Syntax;
    using Microsoft.CodeAnalysis.MSBuild;
    using System.Threading.Tasks;

    namespace Kardex.LC3xx.CreateApiDokumentation
    {
        //Patch to work with VS2013
        //  https://support.microsoft.com/en-us/kb/2971005

        class Program
        {
            private static void Main(string[] args)
            {
                Run(args).Wait();

                Console.ReadLine();
            }

            private async static Task Run(string[] args)
            {
                var path = Path.GetDirectoryName(typeof (Program).Assembly.Location);
                var sln = Path.Combine(path, "xxx.sln");

                var workspace = MSBuildWorkspace.Create();
                var solution = await workspace.OpenSolutionAsync(sln);


                Project project = solution.Projects.First(x => x.Name == "bbbb");
                var compilation = await project.GetCompilationAsync();

                foreach (var @class in compilation.GlobalNamespace.GetNamespaceMembers().SelectMany(x=>x.GetMembers()))
                {
                    Console.WriteLine(@class.Name);
                    Console.WriteLine(@class.ContainingNamespace.Name);
                }

                var classVisitor = new ClassVirtualizationVisitor();

                foreach (var syntaxTree in compilation.SyntaxTrees)
                {
                    classVisitor.Visit(syntaxTree.GetRoot());                
                }

                var classes = classVisitor.Classes;             
            }

            class ClassVirtualizationVisitor : CSharpSyntaxRewriter
            {
                public ClassVirtualizationVisitor()
                {
                    Classes = new List<ClassDeclarationSyntax>();
                }

                public List<ClassDeclarationSyntax> Classes { get; set; }

                public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
                {
                    node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
                    Classes.Add(node); // save your visited classes
                    return node;
                }
            }
        }
    }

4
创建一个SymbolVisitor,覆盖VisitNamedType以处理每个类型(可能不是类)。
然后将其传递给compilation.Assembly.Accept()

2
我认为 SymbolVisitor 不会“遍历”层次结构,所以用户还必须通过覆盖 VisitAssemblyVisitNamespace 来遍历层次结构,对吗? - Kirk Woll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接