Roslyn中VisitExpressionStatement未更新表达式的问题排查
问题排查与解决
核心原因与修复步骤
必须返回修改后的语法节点
Roslyn的语法节点是不可变的,CSharpSyntaxRewriter的重写方法如果只处理逻辑但不返回新构造的节点,原节点不会被替换。比如你的VisitExpressionStatement方法最后必须返回修改后的ExpressionStatementSyntax,而不是直接调用base.VisitExpressionStatement(node)或不返回值。精准匹配目标调用节点
你当前重写的是ExpressionStatement,但实际要替换的是其中的InvocationExpression(即GetCustomer的调用逻辑)。建议重写VisitInvocationExpression方法,针对性匹配目标调用:- 先判断当前调用是否为
GetCustomer方法 - 再验证它的调用实例是否是
DALFactory.Factory.GetDAL<ICustomerDAL>() - 匹配成功后,构造新的调用节点
this.customerDAL.GetCustomer(customerId)
示例代码片段:
public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { // 匹配 GetCustomer 调用 if (node.Expression is MemberAccessExpressionSyntax memberAccess && memberAccess.Name.Identifier.Text == "GetCustomer" // 匹配 DALFactory.Factory.GetDAL<ICustomerDAL>() 部分 && memberAccess.Expression is InvocationExpressionSyntax getDalInvocation && getDalInvocation.Expression is MemberAccessExpressionSyntax getDalMemberAccess && getDalMemberAccess.Name.Identifier.Text == "GetDAL" && getDalMemberAccess.Expression is MemberAccessExpressionSyntax factoryAccess && factoryAccess.Name.Identifier.Text == "Factory" && factoryAccess.Expression is IdentifierNameSyntax dalFactory && dalFactory.Identifier.Text == "DALFactory") { // 构造 this.customerDAL.GetCustomer(customerId) var newMemberAccess = SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("customerDAL")); var newInvocation = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, newMemberAccess, SyntaxFactory.IdentifierName("GetCustomer")), node.ArgumentList); return newInvocation; } return base.VisitInvocationExpression(node); }- 先判断当前调用是否为
确保将重写结果应用到文档
重写完成后,必须把新的语法根节点替换回原文档并保存,否则修改不会生效:var originalRoot = await document.GetSyntaxRootAsync(); var rewriter = new BllRewriter(); var newRoot = rewriter.Visit(originalRoot); if (newRoot != originalRoot) { document = document.WithSyntaxRoot(newRoot); var solution = document.Project.Solution; workspace.TryApplyChanges(solution); }校验节点匹配逻辑的准确性
调试时确认你的匹配条件是否准确命中目标节点,比如泛型参数ICustomerDAL的判断,可补充如下逻辑:if (getDalInvocation.Expression is GenericNameSyntax genericGetDal && genericGetDal.Identifier.Text == "GetDAL" && genericGetDal.TypeArgumentList.Arguments.Any(arg => arg is IdentifierNameSyntax idName && idName.Identifier.Text == "ICustomerDAL")) { // 执行替换逻辑 }
内容的提问来源于stack exchange,提问作者James Moot
相关产品推荐
相关产品推荐

