【问题标题】:Lambda expression not correct - need to return a boolean FuncLambda 表达式不正确 - 需要返回一个布尔函数
【发布时间】:2014-10-14 01:38:20
【问题描述】:

我有一个从另一个站点复制的代码块,用于解析 BindingSourceView 的过滤器表达式。原始代码是为 VS 2008 和更早的 .net 框架构建的,但它不适用于 VS 2010 和 .Net 框架 V4,因为 Expression.Lambda 函数不再返回可以正确转换的函数。

<T> = Note

public class PostfixExpressionToLambda<T>
{
    .
    .
    .

/// <summary>
/// This is the core function, it generates the Lambda.
/// </summary>
/// <param name="postfixExpression"></param>
/// <returns></returns>
private LambdaExpression GenerateExpressionFromPostfixList(IList<string> postfixExpression)
    {
        Stack<Expression> stack = new Stack<Expression>();
        Dictionary<String, ParameterExpression> parameters = new Dictionary<String, ParameterExpression>();
        List<ParameterExpression> parametersList = new List<ParameterExpression>();

        parametersList.Add(inputObj);
        Int32 i = 0;
        while (i < postfixExpression.Count)
        {
            String token = postfixExpression[i];
            //First of all check if is a name of a property of the object
            if (propertyNames.Any(p => p.Name == token))
            {
                stack.Push(Expression.Property(inputObj, token));
            }
            else if (IsMemberAccessOperator(token))
            {
                //Member access operator could advance the index. This because the syntax used to invoke a method
                //is not so good with postfix :) that because Name.Contains('xxx') becomes Name Contains . xxx because
                //parenthesis are used to precedence.
                ExecuteMemberAccessOperator(token, stack, postfixExpression, ref i);
            }
            else if (IsBinaryOperator(token))
            {
                ExecuteBinaryOperator(token, stack);
            }
            else if (IsUnaryOperator(token))
            {
                ExecuteUnaryOperator(token, stack);
            }
            else if (IsParameter(token))
            {
                ExecuteParameter(token, stack, parameters, parametersList);
            }
            else
            {
                stack.Push(Expression.Constant(token));
            }
            i++;
        }

    .
    .
    .

        Expression final = stack.Pop();
        if (stack.Count > 0) throw new ArgumentException("The postfix expression is malformed");
        return Expression.Lambda(final, parametersList.ToArray());
    }
    .
    .
    .
}

上面显示的行返回一个字符串类型的 lambda 表达式,而不是布尔类型。检查 lambda 值,返回的类型是:

.Lambda #Lambda1<System.Func`2[Armada.DataModels.Note,System.String]>Armada.DataModels.Note $object) {    "[CorrespondenceCategoryID]=6" }

从这个方法调用:

public Expression<Func<T, P1, RetType>> Execute<P1, RetType>(IList<String> postfixExpression)
    {
        LambdaExpression lambda = GenerateExpressionFromPostfixList(postfixExpression);
        return (Expression<Func<T, P1, RetType>>)lambda;
    }

当表达式函数返回的值是字符串时,它会抛出一个异常,试图将返回的表达式转换为布尔类型。 RetType=布尔值。例外是:

无法将“System.Linq.Expressions.Expression`1[System.Func`2[Armada.DataModels.Note,System.String]]”类型的对象转换为“System.Linq.Expressions.Expression`1”类型[System.Func`2[Armada.DataModels.Note,System.Boolean]]'。

我认为解决此问题的简单方法是为 lambda 函数提供我想要返回的委托(来自上一个代码块):

private LambdaExpression GenerateExpressionFromPostfixList<P1, RetType>(IList<string> postfixExpression)
{
    .
    .
    .
    return Expression.Lambda<Func<T, P1, RetType>>(final, parametersList.ToArray());
}

但是,在运行时,这最后一行现在会抛出一个错误,表明

为 lambda 声明提供的参数数量不正确

被解析的字符串非常简单:“[CorrespondenceCategoryID]=6”

应该为列表中的每个对象评估结果表达式,以确定哪些将包含在绑定源列表中。单个参数有一个 NodeType 参数和一个 Note 类型(我要过滤的对象。

在弄清楚如何修改原始代码以正确返回正确的类型或找出传递给 Lambda 方法的参数错误的原因方面,我们将不胜感激。

【问题讨论】:

  • 不仅仅是运算符反映了您使用的语言,"[CorrespondenceCategoryID]=6" 实际上应该是"[CorrespondenceCategoryID]==6"?
  • 不,原始代码应该解析可以分配给 BindingListView 过滤器字符串的过滤器表达式的子集。如前所述,原始代码以某种方式返回了带有布尔结果的 lambda 函数,而当前版本在我需要布尔结果时试图返回字符串结果。或者原始转换在 .Net v4 之前工作,但由于它不想将函数转换为布尔值而失败。
  • 如果您从 VS2010 面向 .NET 3.5,您能否确认代码仍然有效?
  • “inputObj”从何而来?

标签: c# linq parsing lambda linq-expressions


【解决方案1】:

我试图做的是允许用户动态排序和过滤网格中的列。事实证明,已经有一个优秀的库可以做到这一点,所以我下载了它并用它代替了这段代码:

Dynamic Linq - Part 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    • 2021-12-24
    • 1970-01-01
    • 2018-08-11
    • 2013-09-15
    相关资源
    最近更新 更多