编译 CompilationUnitSyntax 的正确方法

Proper way to compile CompilationUnitSyntax

我有以下代码片段

 var compilationUnit = SyntaxFactory.CompilationUnit()
            .AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")))
            .AddMembers(
                SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName("MyNamespace"))
                    .AddMembers(SyntaxFactory.ClassDeclaration("MyClass").AddMembers(
                        SyntaxFactory.MethodDeclaration(SyntaxFactory.ParseTypeName("void"), "Main")
                            .WithBody(SyntaxFactory.Block())))).NormalizeWhitespace();

但是,当我直接从编译单元使用 SyntaxTree 时,似乎无法使用 Roslyn 编译它 - 就像那样

        CSharpCompilation compilation = CSharpCompilation.Create(
           assemblyName: "MyAssembly",
           syntaxTrees: new [] { compilationUnit.SyntaxTree },
           references: references,
           options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
       );

我找不到比使用

重新创建 SyntaxTree 更好的方法了
CSharpSyntaxTree.ParseText(compilationUnit.ToFullString())

并将其传递给 CSharpCompilation.Create 方法。有没有更好的编译 CompilationUnitSyntax 的方法?

您正在寻找 CSharpSyntaxTree.Create(compilationUnit)

从语法树创建编译的方式没有任何问题。问题在于您创建语法树的方式,特别是 void 关键字(如错误所示)。

如果你写这段代码:

SyntaxFactory.ParseTypeName("void").GetDiagnostics()

那么已经报错了

您可以手动为 void 类型创建一个 TypeName 对象,而不是 ParseTypeName

SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword))

适合我的完整代码(从您的代码中简化以删除不必要的语法节点):

var compilationUnit = SyntaxFactory.CompilationUnit()
    .AddMembers(SyntaxFactory.ClassDeclaration("MyClass").AddMembers(
        SyntaxFactory.MethodDeclaration(
                SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)),
                "Main")
            .WithBody(SyntaxFactory.Block())))
    .NormalizeWhitespace();

CSharpCompilation compilation = CSharpCompilation.Create(
    assemblyName: "MyAssembly",
    syntaxTrees: new[] { compilationUnit.SyntaxTree },
    references: references,
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);