在 InvocatioExpression 中插入新方法调用

Insert new method call in InvocatioExpression

我正在编写 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: The item specified is not the element of a list."

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

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

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

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

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

我是这样解决的:

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