无法从变量解析表达式常量

问题描述 投票:0回答:1

this post标记的答案之后,我将

Evaluator.cs
复制到我的项目中进行部分评估,以便能够解析表达式的局部变量。不管怎样,我似乎遗漏了一些东西,因为对我来说它并没有简化表达式,并且常量被保留为原始表达式作为编译器生成的匿名类的实例:

我的访问者的 VisitMember 方法如下所示:

protected override Expression VisitMember(MemberExpression m)
{
    if (m.Expression != null && m.Expression.NodeType == ExpressionType.Parameter)
    {
        sqlBuilder.AddColumn(m.Member.GetFieldName());
        return m;
    }
    else if (m.Expression != null && m.Expression.NodeType == ExpressionType.Constant)
    {
        var partialEval = Evaluator.PartialEval(m.Expression);
        this.Visit(partialEval);
        return m;
    }

    throw new NotSupportedException(string.Format("The member '{0}' is not supported", m.Member.Name));
}

更新:为了更好地理解我想要做什么,这是我正在执行的单元测试,以测试输出 sql 是否正确:

[Theory]
[InlineData("Test1")]
[InlineData("Test2")]
[InlineData("Test3")]
public void SelectWhereExpression_NameEquals(string name)
{
    using var sqlbuilder = GetSpecificBuilder();
    string sql = sqlbuilder.Select()
                           .Where(obj => obj.Name == name)
                           .Build().SqlCommand;

    var selectSql = SelectAllRecordsExpectedSql.Remove(SelectAllRecordsExpectedSql.Length - 1, 1);

    Assert.Equal($"{selectSql} WHERE (Name = '{name}')", sql);
}

.Where() 方法将表达式作为参数,并使用该表达式调用我的 SqlVisitor:

public virtual SqlBuilder<T> Where(Expression<Func<T, bool>> expression)
{
    BuiltObject.Append(" WHERE");
    ExpressionToSQLVisitor<T> expressionToSQL = new(this);
    expressionToSQL.Visit(expression);
    return this;
}

我做错了什么?

c# .net expression-trees
1个回答
0
投票

会稍微改变你的代码。您打算如何呈现值取决于您。 主要变化是覆盖

VisitConstant
中的
ExpressionToSQLVisitor

protected override Expression VisitMember(MemberExpression node)
{
    if (node.Expression?.NodeType == ExpressionType.Parameter)
    {
        sqlBuilder.AddColumn(node.Member.GetFieldName());
        return node;
    }
    else 
    {
        var partialEval = Evaluator.PartialEval(node);
        if (!ReferenceEquals(partialEval, node))
            return Visit(partialEval);
    }

    throw new NotSupportedException(string.Format("The member '{0}' is not supported", node.Member.Name));
}

protected override Expression VisitConstant(ConstantExpression node)
{
    sqlBuilder.AddValue(node.Value);
    return node;
}
© www.soinside.com 2019 - 2024. All rights reserved.