【问题标题】:Convert Expression to Expression<Func<T, bool>>将表达式转换为表达式<Func<T, bool>>
【发布时间】:2016-02-03 02:12:10
【问题描述】:

如果在T 上创建了表达式实例,是否可以将Expression 转换为Expression&lt;Func&lt;T, bool&gt;&gt;

最后我有列表List&lt;Expression&gt;,需要在Expression&lt;Func&lt;T, bool&gt;&gt; 上生成,其中List&lt;Expression&gt; 的每个表达式都与AND 聚合。

【问题讨论】:

  • 参数不应该是List&lt;Expression&lt;Func&lt;T, bool&gt;&gt;&gt;吗?
  • 不,我使用 Kendo Grid,其中 DataSourceRequest.Filters.Select(x=>) x 只有一个方法 CreateExpression,它返回表达式类型
  • 好的,但是if instance of Expression was created on T 表示列表中的每个表达式都应该可以转换为Expression&lt;Func&lt;T,bool&gt;&gt;
  • 应该,这是我的问题。
  • @kosnkov 不知道实际的输入表达式是什么,就不可能知道如何将它们转换成你想要的。

标签: c# expression


【解决方案1】:

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

你可能想要list.Aggregate(Expressions.AndAlso)

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

【讨论】:

  • #SLaks Expression.Lambda>(..., parameter) 那么参数是什么?
  • @kosnkov:您希望表达式使用的Expression.Parameter(typeof(T))
  • @SLaks 我试过这个,当查询被具体化时,我得到了异常,附加信息“参数”未绑定在特定的 LINQ to Entities 查询表达式中“
  • @SLaks 和我用 Kendo 扩展这样创建这个表达式: dataSourceRequest.Filters.Select(x=>x.CreateFilterExpression(Expression.Paramete‌​r(typeof(T)))).ToList( )
  • @kosnkov:您需要将其更改为使用单个参数表达式实例。
【解决方案2】:

这是可能的,但列表中的每个表达式实际上都必须是 Expression&lt;Func&lt;T, bool&gt;&gt; 实例。

编辑:事实证明,您使用的是Kendo.Mvc.IFilterDescriptor.CreateFilterExpression,它实际上构建了一个MethodCallExpressions。

以下辅助方法应该可以完成这项工作(适用于 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 是这样创建的: dataSourceRequest.Filters.Select(x=>x.CreateFilterExpression(Expression.Parameter(typeof(T)))).ToList ()
  • 什么真正返回CreateFilter?展示一些示例实现。或者当转换失败时,您无法转换的表达式的实际类型是什么?
  • 无法将“System.Linq.Expressions.InstanceMethodCallExpressionN”类型的对象转换为类型(这里是 Expression> 的类型)
  • @kosnkov 好的,我想我明白了。可以试试更新答案,可惜不能测试(没有剑道环境)。
  • 来自 SLaks 的解决方案有效,但我非常感谢您的帮助,非常感谢您
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 2012-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
  • 1970-01-01
相关资源
最近更新 更多