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

2

5

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.

Takamatsu answered 2/2, 2016 at 14:53 Comment(5)
Shouldn't the arguments to be a List<Expression<Func<T, bool>>>?Civic
no, I use Kendo Grid, where DataSourceRequest.Filters.Select(x=>) x has only one method CreateExpression and it returns Expresssion TypeTakamatsu
Ok, but still if instance of Expression was created on T means that every expression in the list should be cast-able to Expression<Func<T,bool>>?Civic
It should and that is my question how to do it.Takamatsu
@Takamatsu Without knowing what the actual input expressions are, there's no possible way to know how to convert them into what you want.Tourcoing
C
6

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)

Cholecystotomy answered 2/2, 2016 at 14:56 Comment(7)
#SLaks Expression.Lambda<Func<T, bool>>(..., parameter) what parameter is then ?Takamatsu
@kosnkov: The Expression.Parameter(typeof(T)) that you want your expressions to use.Cholecystotomy
@Cholecystotomy I tried this one, and when query is materiaized I got exception with additional information "The parameter "was not bound in the specyfic LINQ to Entities query expression "Takamatsu
@Cholecystotomy and I create this expression with Kendo extension this way: dataSourceRequest.Filters.Select(x=>x.CreateFilterExpression(Expression.Paramete‌​r(typeof(T)))).ToList()Takamatsu
@kosnkov: You need to change that to use a single parameter expression instance.Cholecystotomy
@Cholecystotomy can you elaboreate at least one sentence more, what should I do ?Takamatsu
@kosnkov: Create a single Expression.Parameter(typeof(T)), then pass it to all of the clauses and to the Lambda.Cholecystotomy
C
2

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);
        }
    }
}
Civic answered 2/2, 2016 at 15:27 Comment(5)
I am unable do cast, my List<expression> is created this way: dataSourceRequest.Filters.Select(x=>x.CreateFilterExpression(Expression.Parameter(typeof(T)))).ToList()Takamatsu
What really returns CreateFilter? Show some sample implementation. Or when the cast fails, what is the actual type of the expression that you are unable to cast?Civic
Unable to cast object of type 'System.Linq.Expressions.InstanceMethodCallExpressionN' to type (here is type of Expression<Func<T, bool>>)Takamatsu
@Takamatsu Ok, I think I got the case. You can try the update answer, unfortunately can't test it (don't have Kendo environment).Civic
Solution from SLaks works, but I really appreciate your help, thank you very muchTakamatsu

© 2022 - 2024 — McMap. All rights reserved.