我有一个代码块,我从另一个站点复制,用于解析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());
}
.
.
.
}
上面显示的行返回一个String类型为String的表达式,而不是boolean类型。检查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]]&#39;的对象输入&#39; System.Linq.Expressions.Expression`1 [System.Func`2 [Armada.DataModels.Note,System.Boolean]]&#39;。
我认为解决这个问题的简单方法是使用我想要返回的委托(从前面的代码块)提供lambda函数:
private LambdaExpression GenerateExpressionFromPostfixList<P1, RetType>(IList<string> postfixExpression)
{
.
.
.
return Expression.Lambda<Func<T, P1, RetType>>(final, parametersList.ToArray());
}
但是,在运行时,最后一行现在抛出一个错误,指示
为lambda声明提供的参数数量不正确
正在解析的字符串非常简单:&#34; [CorrespondenceCategoryID] = 6&#34;
应该为列表中的每个对象评估结果表达式,以确定哪些对象将包含在绑定源列表中。单个参数的NodeType为Parameter,还有Type of Note(我试图过滤的对象。
在弄清楚如何修改原始代码以正确返回正确的类型,或者弄清楚为什么传递给Lambda方法的参数是错误的时候,我们将不胜感激。
答案 0 :(得分:0)
我尝试做的是允许用户动态排序和过滤网格中的列。事实证明,已经有一个很好的库可以做到这一点,所以我下载并使用它来代替这个代码: