【问题标题】:Roslyn SyntaxTree - Changing Field valueRoslyn SyntaxTree - 更改字段值
【发布时间】:2020-12-06 23:56:28
【问题描述】:

使用 Roslyn SyntaxTree API,我想用新值替换文字值“UV254”。 示例:

public class Analog
{
   public const string Value = "UV254";
}

更新后

public class Analog
{
   public const string Value = "UV220";
}

我想出了以下解决方案,但我怀疑这可以简化:

string sourceCode = "public class Analog { public const string Value = \"UV254\"; public const string Description = \"A Description\";}";

SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
CompilationUnitSyntax syntaxRoot = syntaxTree.GetCompilationUnitRoot();

LiteralExpressionSyntax afterLiteralExpressionSyntax = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("UV220"));

LiteralExpressionSyntax beforeLiteralExpressionSyntax = null;
foreach (VariableDeclarationSyntax variableDeclarationSyntax in syntaxRoot.DescendantNodes().OfType<VariableDeclarationSyntax>())
{
    foreach(VariableDeclaratorSyntax variableDeclaratorSyntax in variableDeclarationSyntax.Variables)
    {
        if(variableDeclaratorSyntax.Identifier.ValueText == "Value")
        {
            beforeLiteralExpressionSyntax = variableDeclaratorSyntax.DescendantNodes().OfType<LiteralExpressionSyntax>().Single();
            break;
        }
    }
    if(beforeLiteralExpressionSyntax != null)
    {
        break;
    }
}
var newRoot = syntaxRoot.ReplaceNode(beforeLiteralExpressionSyntax, afterLiteralExpressionSyntax);
var fixedTree = newRoot.SyntaxTree.WithRootAndOptions(newRoot, syntaxTree.Options);

这可以简化吗? 感谢您的帮助。

【问题讨论】:

    标签: c# abstract-syntax-tree roslyn


    【解决方案1】:

    我认为您可以使用一些 LINQ 来缩短beforeLiteralExpressionSyntax 的确定性。您可以改为编写以下内容:

                LiteralExpressionSyntax beforeLiteralExpressionSyntax =
                    syntaxRoot.DescendantNodes().OfType<VariableDeclarationSyntax>()
                    .SelectMany(decl => decl.Variables)
                    .FirstOrDefault(declarator => declarator.Identifier.ValueText == "Value")
                    ?.DescendantNodes().OfType<LiteralExpressionSyntax>()
                    .Single();
    

    如果未找到该字段,这会将 null 值分配给 beforeLiteralExpressionSyntax。如果您确定该字段将始终存在,您可以将 FirstOrDefault 替换为 First 并将 ?. 替换为 .

    除此之外,我不认为您可以做很多事情来简化代码。我与 Roslyn 合作的经验是,最终浏览语法树、从中挑选出相关位并对其进行更改是相当复杂的,但我想其中一些是不可避免的,因为它反映了 C# 语言的复杂性。

    【讨论】:

    • 谢谢,我喜欢!
    猜你喜欢
    • 2013-01-24
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 2017-09-19
    • 2015-10-18
    • 2011-07-24
    相关资源
    最近更新 更多