【问题标题】:Roslyn - how to add statements after matching InvocationExpressionSyntaxRoslyn - 如何在匹配 InvocationExpressionSyntax 后添加语句
【发布时间】:2013-10-01 08:09:28
【问题描述】:

我正在使用 Roslyn 库。 我想在匹配行之后添加语句:这是要求。 首先我想找到以下行:

_container.RegisterInstance(NavigationService);

然后我想在上面的行之后添加以下语句:

_container.RegisterInstance<ISessionStateService>(SessionStateService);
_container.RegisterInstance<IFlyoutService>(FlyoutService);

任何帮助将不胜感激。

编辑:(我已经创建了表达式,但是现在如何将这两个表达式添加到我的 targetExpression 中?

   string strContent = File.ReadAllText(strPath);
        SyntaxTree tree = SyntaxTree.ParseText(strContent);
        var targetExpression = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>()
                .FirstOrDefault(
                    x => x.Expression.ToString().Contains("_container.RegisterInstance") && x.ArgumentList.ToString().Contains("NavigationService"));

        InvocationExpressionSyntax replacementNode1 =
            Syntax.InvocationExpression(Syntax.ParseExpression(@"_container.RegisterInstance<ISessionStateService>(SessionStateService);"));

        InvocationExpressionSyntax replacementNode2 =
           Syntax.InvocationExpression(Syntax.ParseExpression(@"_container.RegisterInstance<IFlyoutService>(FlyoutService);"));

        MethodDeclarationSyntax targetMethod = (MethodDeclarationSyntax)targetExpression.Parent.Parent.Parent;

        List<InvocationExpressionSyntax> list = targetMethod.DescendantNodes().OfType<InvocationExpressionSyntax>().ToList();
        int index = list.IndexOf(targetExpression);

        list.Insert(index + 1, replacementNode1);
        list.Insert(index + 1, replacementNode2);

现在的问题是如何获取我更新的树?表示如何更新我的列表并通过这些更改获取树。

编辑:现在我可以生成添加节点,但唯一的问题是格式。间距不正确。这是代码:

   string strContent = File.ReadAllText(strPath);
        SyntaxTree tree = SyntaxTree.ParseText(strContent);

        ExpressionStatementSyntax expressionStatementSyntax =
            Syntax.ExpressionStatement(Syntax.ParseExpression("_container.RegisterInstance(NavigationService);"));

        var targetBlock =
            tree.GetRoot()
                .DescendantNodes()
                .OfType<BlockSyntax>()
                .FirstOrDefault(x => x.Statements.Any(y => y.ToString().Contains("_container.RegisterInstance")));

        StatementSyntax syn1 =
            Syntax.ParseStatement(@"_container.RegisterInstance<ISessionStateService>(SessionStateService);");
        StatementSyntax syn2 = Syntax.ParseStatement(@"_container.RegisterInstance<ISessionStateService>(SessionStateService2);");

        List<StatementSyntax> newSynList = new List<StatementSyntax> { syn1, syn2 };

        SyntaxList<StatementSyntax> blockWithNewStatements = targetBlock.Statements;

        foreach (var syn in newSynList)
        {
            blockWithNewStatements = blockWithNewStatements.Insert(1, syn);
        }

        BlockSyntax newBlock = Syntax.Block(blockWithNewStatements);

        var newRoot = tree.GetRoot().ReplaceNode(targetBlock, newBlock);

它生成所有行左对齐的输出。有什么建议吗?

【问题讨论】:

  • 到目前为止你有什么?
  • 我只能找到我的目标行...但我不确定如何在我的目标行之后添加语句。字符串 strContent = File.ReadAllText(strPath); SyntaxTree 树 = SyntaxTree.ParseText(strContent); var targetMethod = tree.GetRoot().DescendantNodes().OfType() .FirstOrDefault( x => x.Expression.ToString().Contains("_container.RegisterInstance") && x.ArgumentList.ToString()。包含("NavigationService"));
  • 我已经编辑了线程.. 我能够获得 targetExpression 并且还创建了两个我想附加到我的 targetExpression 的节点...有什么建议吗?

标签: c# roslyn


【解决方案1】:

编辑后,剩下的主要问题似乎是关于处理行格式。在这两种情况下,一旦你获得了最终的根目录,就可以调用格式化程序来清理它。你有两个选择:

  1. 完成后,您可以在节点上调用 NormalizeWhitespace() 扩展,这会非常粗鲁地将所有节点重新格式化为远程“合理”的格式。如果您不关心保留您拥有的任何格式,并且只是希望输出看起来不那么糟糕,那么这是一个简单的选项。
  2. 您可以引用 Roslyn.Services 程序集,然后在顶部添加“使用 Roslyn.Services”(如果还没有的话)。从那里,有一个 Format() 方法,它是一个更高级的格式化程序,它试图保持原样缩进,尊重用户已有的内容,等等。如果你在你创建的节点上粘贴语法注释,你可以然后将该注释传递给此格式化程序,以便它知道保持文件的其余部分保持不变。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 1970-01-01
    • 2017-11-04
    • 1970-01-01
    相关资源
    最近更新 更多