Как получить автопринадлежности в одной строке при генерации кода с помощью Roslyn? - PullRequest
0 голосов
/ 28 июня 2018

У меня есть следующий частичный код, который я использую для генерации контрактов данных на основе файла 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();
    }

Код работает на удивление хорошо с одной маленькой ошибкой. Сгенерированный код выглядит следующим образом:

public string VariableName
{
    get;
    set;
}

И я действительно хочу, чтобы это выглядело так:

public string VariableName { get; set; }

Кто-нибудь знает, как это сделать, если это возможно?

Ответы [ 2 ]

0 голосов
/ 15 сентября 2018

У меня точно такая же проблема. В моем случае я сохранял код в файл после преобразования его в строку, например, такую:

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

    File.WriteAllText(destFileName, codeAsString);
}

Итак, в этом случае я просто решил эту проблему, запустив замену регулярного выражения в строке, в методе расширения:

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; }");
}

И затем вызвать его после преобразования в строку:

        var codeAsString = ns.NormalizeWhitespace()
                         .ToFullString()
                         .FormatAutoPropertiesOnOneLine();

Вы не уточняете, как вы выполняете этап написания файла (если есть), поэтому, если это не имеет отношения к вашему делу, я прошу прощения за то, что вы не задали свой вопрос на 100%. В любом случае, кому-то еще это может быть полезно

0 голосов
/ 28 июня 2018

В качестве одного из простых решений (другой способ создания узлов и токенов с правильными пустяками) просто используйте 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: " "));
}
...