【问题标题】:Insert new method call in InvocatioExpression在 InvocatioExpression 中插入新的方法调用
【发布时间】:2015-08-27 00:55:16
【问题描述】:

我正在编写一个带有提供程序的 Visual Studio 代码修复程序,它将在这种语句中插入 AsEnumerable 调用:

model.clients.Take(10).Select(c => new Client(c));

我能够检测到此类语句,但在 Select 方法之前插入 AsEnumerable 时遇到问题。这是我尝试过的:

        var expressionSyntax = SyntaxFactory.ParseExpression(".AsEnumerable()");
        var memberAccessExpressionSyntax = invocationExpr.Expression as MemberAccessExpressionSyntax;

        var root = await document.GetSyntaxRootAsync(cancellationToken);

        var newRoot = root.InsertNodesAfter(memberAccessExpressionSyntax.Expression, new[] {expressionSyntax});

        return document.WithSyntaxRoot(newRoot);

但我明白了

"System.InvalidOperationException: 指定的项目不是 列表的元素。”

查看堆栈跟踪:https://gist.github.com/anonymous/02c41f232829163b25ae

调用InsertNodesAfter方法的正确方法是什么?

【问题讨论】:

  • 堆栈跟踪是什么?
  • @SLaks 已添加到问题中。
  • InsertNodesAfter 仅适用于列表中的节点。方法调用不是一个列表;你需要拼接一个新的调用表达式。
  • @SLaks:我该怎么做?
  • 你想在哪里插入呼叫?

标签: c# roslyn


【解决方案1】:

我就是这样解决的:

var memberAccessExpressionSyntax = invocationExpr.Expression as MemberAccessExpressionSyntax;

var root = await document.GetSyntaxRootAsync(cancellationToken);

var accessExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, memberAccessExpressionSyntax.Expression, SyntaxFactory.IdentifierName("AsEnumerable"));

var invocationExpression = SyntaxFactory.InvocationExpression(accessExpression);
var enumerableMemberAccessExpression = memberAccessExpressionSyntax.WithExpression(invocationExpression);

root = root.ReplaceNode(invocationExpr, invocationExpr.WithExpression(enumerableMemberAccessExpression));

【讨论】:

    【解决方案2】:

    InsertNodesAfter 仅适用于列表中的节点。方法调用不是一个列表,而是一个调用表达式树。

    您需要将XXX.Select(...) 调用中的表达式替换为XXX.AsEnumerable()(重复使用相同的XXX 节点)。

    要了解这些表达式树的工作原理,请使用 Roslyn 语法可视化工具。

    【讨论】:

    • 问题是在调用 Select 方法之前可能有可变数量的方法调用,所以我不想重建所有方法并附加 AsEnumerable。
    • 您不必重建所有这些。找到你想插入它的那个,然后你将用 x.Bar().Foo() 替换对 x.Foo() 的调用。考虑它的最好方法可能是添加一堆额外的括号:x.Foo() 可以被认为是 (x).Foo(),你可以用 (x.Bar() 替换那个内部的东西).Foo().
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 2021-12-06
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多