使用 Roslyn 生成“只读记录结构”

Generate a 'readonly record struct' using Roslyn

提问人:ASi 提问时间:9/13/2023 最后编辑:ASi 更新时间:9/15/2023 访问量:64

问:

我无法使用 Roslyn 生成只读记录结构。

我的代码:

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

var tree = SyntaxFactory.CompilationUnit()
    .AddMembers(
            SyntaxFactory.RecordDeclaration(
                SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                SyntaxFactory.Identifier("A"))
            .WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))
            .AddModifiers(
                        SyntaxFactory.Token(SyntaxKind.PublicKeyword),
                        SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))
            .WithClassOrStructKeyword(
                SyntaxFactory.Token(SyntaxKind.StructKeyword))
            .WithParameterList(
                SyntaxFactory.ParameterList()))
    .NormalizeWhitespace();

Console.WriteLine(tree.ToFullString());

var refApis = AppDomain.CurrentDomain.GetAssemblies()
    .Where(a => !a.IsDynamic)
    .Select(a => MetadataReference.CreateFromFile(a.Location));

var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);

var compilation = CSharpCompilation.Create("something", new SyntaxTree[] { tree.SyntaxTree }, refApis, options);
var diag = compilation.GetDiagnostics().Where(e => e.Severity == DiagnosticSeverity.Error).ToList();

foreach (var d in diag)
{
    Console.WriteLine(d);
}

Console.ReadLine();

我得到这样的结果“public readonly record struct A();” 以及这样的错误“(1,31):错误 CS0106:”readonly“修饰符对此元素无效。

C# Roslyn 代码分析 NET-7.0

评论

0赞 Martin Liversage 9/13/2023
这很奇怪。我尝试使用相同的语法树,但出现完全相同的编译错误。但是,您也可以使用以下方法创建语法树,这样编译时不会出现错误。检查两个语法树时,它们看起来是一样的,但必须有一些微小的差异,这些差异不会立即显现出来,从而触发编译错误。CSharpSyntaxTree.ParseText("public readonly record struct A();")

答:

3赞 Youssef13 9/15/2023 #1

问题在于,您正在创建的记录声明具有 .即使添加 struct 关键字,它也不会更改最初创建的 SyntaxKind。要解决此问题,您需要按如下方式执行:SyntaxKind.RecordDeclarationSyntaxKind.RecordStructDeclaration

            SyntaxFactory.RecordDeclaration(
                SyntaxKind.RecordStructDeclaration,
                SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                SyntaxFactory.Identifier("A"))

而不是

            SyntaxFactory.RecordDeclaration(
                SyntaxFactory.Token(SyntaxKind.RecordKeyword),
                SyntaxFactory.Identifier("A"))