You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Roslyn中VisitExpressionStatement未更新表达式的问题排查

问题排查与解决

核心原因与修复步骤

  • 必须返回修改后的语法节点
    Roslyn的语法节点是不可变的,CSharpSyntaxRewriter的重写方法如果只处理逻辑但不返回新构造的节点,原节点不会被替换。比如你的VisitExpressionStatement方法最后必须返回修改后的ExpressionStatementSyntax,而不是直接调用base.VisitExpressionStatement(node)或不返回值。

  • 精准匹配目标调用节点
    你当前重写的是ExpressionStatement,但实际要替换的是其中的InvocationExpression(即GetCustomer的调用逻辑)。建议重写VisitInvocationExpression方法,针对性匹配目标调用:

    1. 先判断当前调用是否为GetCustomer方法
    2. 再验证它的调用实例是否是DALFactory.Factory.GetDAL<ICustomerDAL>()
    3. 匹配成功后,构造新的调用节点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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 08:45:26