簡體   English   中英

使用 Roslyn 生成代碼時,如何在一行上獲得自動屬性?

[英]How do I get autoproperties on one line when generating code with 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();
    }

該代碼在一個小問題上運行得非常好。 生成的代碼如下所示:

public string VariableName
{
    get;
    set;
}

我真的希望它看起來像這樣:

public string VariableName { get; set; }

如果可能的話,有誰知道如何做到這一點?

我遇到了完全相同的問題。 就我而言,我將代碼轉換為類似這樣的字符串后將其保存到文件中:

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% 以您的問題為目標。 無論如何,其他人可能會從中受益。

您可以實現 CSharpSyntaxRewriter 並將其應用於父 SyntaxNode:

public static class WhitespaceFormatter
{
    public static SyntaxNode NormalizeWhitespacesSingleLineProperties(this SyntaxNode node) => 
        node.NormalizeWhitespace().SingleLineProperties();

    public static SyntaxNode SingleLineProperties(this SyntaxNode node) => new SingleLinePropertyRewriter().Visit(node);

    class SingleLinePropertyRewriter : CSharpSyntaxRewriter
    {
        public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) =>
            node.NormalizeWhitespace(indentation: "", eol: " ")
                .WithLeadingTrivia(node.GetLeadingTrivia())
                .WithTrailingTrivia(node.GetTrailingTrivia());
    }
}

使用NormalizeWhitespacesSingleLineProperties將默認空格應用於除將寫入一行的屬性聲明之外的所有內容。 確保之后不要在您的節點上調用FormatNormalizeWhitespace() ,因為它會再次使您的屬性聲明變得混亂。

作為一種簡單的解決方案(另一種方式創建節點和具有正確瑣事的標記),只需將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: " "));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM