Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Expression to Expression<Func<T, bool>>

Tags:

c#

expression

Is that possible to convert Expression to Expression<Func<T, bool>> if instance of Expression was created on T ?

At the end I have list List<Expression> and need to produce on Expression<Func<T, bool>> where each expression of List<Expression> is agregated with AND.

like image 968
kosnkov Avatar asked Feb 02 '16 14:02

kosnkov


2 Answers

Yes; just call Expression.Lambda<Func<T, bool>>(..., parameter), where ... is an expression composed of the expressions you want to combine.

You'd probably want list.Aggregate(Expressions.AndAlso).

If your expressions don't all share the same ParameterExpression, you'll need to rewrite them to do so. (use ExpressionVisitor)

like image 146
SLaks Avatar answered Nov 03 '22 09:11

SLaks


It's possible, but every expression in the list must actually be a Expression<Func<T, bool>> instance.

EDIT: It turns out that you use Kendo.Mvc.IFilterDescriptor.CreateFilterExpression which actually builds a MethodCallExpressions.

The following helper method should do the job (works with both lambda and method call expressions):

public static class Utils
{
    public static Expression<Func<T, bool>> And<T>(List<Expression> expressions)
    {
        var item = Expression.Parameter(typeof(T), "item");
        var body = expressions[0].GetPredicateExpression(item);
        for (int i = 1; i < expressions.Count; i++)
            body = Expression.AndAlso(body, expressions[i].GetPredicateExpression(item));
        return Expression.Lambda<Func<T, bool>>(body, item);
    }

    static Expression GetPredicateExpression(this Expression target, ParameterExpression parameter)
    {
        var lambda = target as LambdaExpression;
        var body = lambda != null ? lambda.Body : target;
        return new ParameterBinder { value = parameter }.Visit(body);
    }

    class ParameterBinder : ExpressionVisitor
    {
        public ParameterExpression value;
        protected override Expression VisitParameter(ParameterExpression node)
        {
            return node.Type == value.Type ? value : base.VisitParameter(node);
        }
    }
}
like image 44
Ivan Stoev Avatar answered Nov 03 '22 09:11

Ivan Stoev