使用Roslyn生成代码时,如何在一行上获得自动属性?

Chr*_*ård 5 c# code-generation roslyn

我有以下部分代码,用于根据面向客户的讲习班等使用的excel文件生成数据合同。

    private PropertyDeclarationSyntax[] GenerateProperties()
    {
        var props = new List<PropertyDeclarationSyntax>();
        props.Add(SF.PropertyDeclaration(SF.ParseTypeName("IMigrationInformation"), "MigrationInformation")
            .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.OverrideKeyword))
            .AddAccessorListAccessors(
                SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                    .WithBody(SF.Block(SF.ReturnStatement(SF.ObjectCreationExpression(SF.ParseTypeName($"{Form.RegistryName}MigrationInformation")))))
            ));
        foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
        {
            props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
                .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
                .AddAccessorListAccessors(
                    SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
                    SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
                ));
        }

        return props.ToArray();
    }
Run Code Online (Sandbox Code Playgroud)

该代码通过一个小障碍就可以很好地工作。生成的代码如下所示:

public string VariableName
{
    get;
    set;
}
Run Code Online (Sandbox Code Playgroud)

我真的希望它看起来像这样:

public string VariableName { get; set; }
Run Code Online (Sandbox Code Playgroud)

有谁知道如何做到这一点?

aud*_*sol 5

我遇到了完全相同的问题。就我而言,我将代码转换为类似这样的字符串后将其保存到文件中:

private void WriteCodeToFile(NamespaceDeclarationSyntax ns)
{
    var codeAsString = ns.NormalizeWhitespace()
                         .ToFullString();

    File.WriteAllText(destFileName, codeAsString);
}
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,我只是通过在扩展方法中对字符串运行正则表达式替换来解决它:

private static readonly Regex AutoPropRegex = new Regex(@"\s*\{\s*get;\s*set;\s*}\s");

public static string FormatAutoPropertiesOnOneLine(this string str)
{
    return AutoPropRegex.Replace(str, " { get; set; }");
}
Run Code Online (Sandbox Code Playgroud)

然后在将其转换为字符串后调用它:

        var codeAsString = ns.NormalizeWhitespace()
                         .ToFullString()
                         .FormatAutoPropertiesOnOneLine();
Run Code Online (Sandbox Code Playgroud)

您没有具体说明如何执行文件写入步骤(如果有),因此如果这与您的情况完全无关,我很抱歉没有 100% 以您的问题为目标。无论如何,其他人可能会从中受益。


Geo*_*ria 1

作为一个简单的解决方案(另一种创建具有正确琐事的节点和标记的方法),只需用于SyntaxNodeExtensions.NormalizeWhitespace(...)您想要在一行中表示的节点:

...
foreach (var field in Form.AllDataFields().Where(f => f.FieldTypeInfo != null))
{
    props.Add(SF.PropertyDeclaration(SF.ParseTypeName(field.FieldTypeInfo.BackingType.Name), field.SafeName)
        .AddModifiers(SF.Token(SyntaxKind.PublicKeyword))
        .AddAccessorListAccessors(
            SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken)),
            SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SF.Token(SyntaxKind.SemicolonToken))
        ).NormalizeWhitespace(indentation: "", eol: " "));
}
Run Code Online (Sandbox Code Playgroud)