将表达式转换为Expression<Func<T, bool>>。

5

如果在 T 上创建了一个 Expression 实例,是否有可能将其转换为 Expression<Func<T, bool>>

最终我有一个 List<Expression>,并需要生成一个Expression<Func<T, bool>>,其中 List<Expression> 的每个表达式都与 AND 聚合。


参数不应该是 List<Expression<Func<T, bool>>> 吗? - Ivan Stoev
不,我使用Kendo Grid,其中的DataSourceRequest.Filters.Select(x =>)x仅具有一个CreateExpression方法,并返回表达式类型。 - kosnkov
好的,但是“如果在T上创建了Expression实例”仍然意味着列表中的每个表达式都可以转换为“Expression<Func<T,bool>>”吗? - Ivan Stoev
这是我的问题,如何实现它。 - kosnkov
1
@kosnkov 如果不知道实际输入表达式是什么,就无法知道如何将它们转换为所需的形式。 - Servy
2个回答

6

是的,只需调用 Expression.Lambda<Func<T, bool>>(..., parameter),其中 ... 是由您想要组合的表达式组成的表达式。

您可能需要使用 list.Aggregate(Expressions.AndAlso)

如果您的表达式不都共享相同的 ParameterExpression,则需要重写它们以这样做。(使用 ExpressionVisitor


#SLaks Expression.Lambda<Func<T, bool>>(..., parameter)中的parameter是什么? - kosnkov
@SLaks和我使用Kendo扩展创建了这个表达式:dataSourceRequest.Filters.Select(x=>x.CreateFilterExpression(Expression.Paramete‌​r(typeof(T)))).ToList() - kosnkov
@kosnkov:你需要将其更改为使用单个参数表达式实例。 - SLaks
@SLaks,您能详细解释多一句话吗?我应该做什么? - kosnkov
@kosnkovпјҡеҲӣе»әдёҖдёӘеҚ•дёҖзҡ„Expression.Parameter(typeof(T))пјҢ然еҗҺе°Ҷе…¶дј йҖ’з»ҷжүҖжңүеӯҗеҸҘе’ҢLambdaгҖӮ - SLaks
显示剩余2条评论

2
可能,但列表中的每个表达式都必须实际上是一个Expression<Func<T, bool>>实例。
编辑:原来您使用Kendo.Mvc.IFilterDescriptor.CreateFilterExpression,它实际上构建了一个MethodCallExpression
以下帮助方法应该能够完成工作(适用于lambda和方法调用表达式):
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);
        }
    }
}

我无法进行强制转换,我的List<expression>是这样创建的:dataSourceRequest.Filters.Select(x=>x.CreateFilterExpression(Expression.Parameter(typeof(T)))).ToList() - kosnkov
CreateFilter 到底返回什么?请展示一些样例实现。或者当强制转换失败时,你无法强制转换的表达式的实际类型是什么? - Ivan Stoev
无法将类型为'System.Linq.Expressions.InstanceMethodCallExpressionN'的对象强制转换为类型(这里是Expression<Func<T, bool>>的类型)。 - kosnkov
@kosnkov 好的,我明白了。你可以尝试更新答案,但很遗憾我无法测试它(没有Kendo环境)。 - Ivan Stoev
SLaks的解决方案可行,但我非常感谢你的帮助,非常感谢。 - kosnkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接