Vote count:
0
I have a block of code that I copied from another site, which is used to parse filter expressions for for a BindingSourceView. The original code was built for VS 2008 and an earlier .net framework, however it did not work with VS 2010 and .Net framework V4 as the Expression.Lambda function no longer returns a function that can be cast properly.
<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());
}
.
.
.
}
The line shown above returns a lambda expression with a type of String, rather than a type of boolean. Examining the lambda value, the type returned is:
.Lambda #Lambda1<System.Func`2[Armada.DataModels.Note,System.String]>Armada.DataModels.Note $object) { "[CorrespondenceCategoryID]=6" }
It is called from this method:
public Expression<Func<T, P1, RetType>> Execute<P1, RetType>(IList<String> postfixExpression)
{
LambdaExpression lambda = GenerateExpressionFromPostfixList(postfixExpression);
return (Expression<Func<T, P1, RetType>>)lambda;
}
which throws an exception trying to cast the expression returned to a boolean type when what the expression function value returned was string. RetType=boolean. The exception is:
Unable to cast object of type 'System.Linq.Expressions.Expression`1[System.Func`2[Armada.DataModels.Note,System.String]]' to type 'System.Linq.Expressions.Expression`1[System.Func`2[Armada.DataModels.Note,System.Boolean]]'.
I thought the easy way to fix this was to provide the lambda function with the delegate that I wanted to return (from the previous code block):
private LambdaExpression GenerateExpressionFromPostfixList<P1, RetType>(IList<string> postfixExpression)
{
.
.
.
return Expression.Lambda<Func<T, P1, RetType>>(final, parametersList.ToArray());
}
However, at runtime, this last line now throws an error indicating that
Incorrect number of parameters supplied for lambda declaration
The string being parsed is pretty simple: "[CorrespondenceCategoryID]=6"
The resulting expression is supposed to be evaluated for each object in a list to determine which are to be included in a binding source list. The single parameter has a NodeType of Parameter, and a Type of Note (the object that I am trying to filter.
Any help would be appreciated in figuring out how to modify the original code to properly return the correct type, or figuring out why the arguments being passed to the Lambda method are wrong.
Thanks, Neil
Lambda expression not correct - need to return a boolean Func
Aucun commentaire:
Enregistrer un commentaire