如何通过多个表达式的组合来组成一个表达式树?

问题描述

| 我正在尝试构造一个“ 0”,该值将由我的实体模型进行评估。我想将其传递给两组lambda,并将其组成所有复杂的表达式树,然后将其传递给数据库以执行。 这是我到目前为止的内容
public class FilterManager<T>
{
    public List<Expression<Func<T,bool>>> Inclusive { get; set; }
    public List<Expression<Func<T,bool>>> Exclusive { get; set; }

    public IQueryable<T> ApplyFilters(IQueryable<T> query)
    {
        var q = query;

        Exclusive.ForEach(exp => q = q.Where(exp)); //works fine
        Inclusive.ForEach(exp => /* ??? */); 

        return q;
    }

    //ctor,etc.
}
这里的想法是我在
Inclusive
添加几个表达式,将它们“或”在一起。例如,如果
T
int
,则代码
fm.Inclusive.Add(x => x > 1);
fm.Inclusive.Add(y => y < 5);

query = fm.ApplyFilters(query);
结果集应与以下内容相同:
query = query.Where(z => z > 1 || z < 5);
没有PredicateBuilder之类的第三方工具,如何才能使ѭ2正常工作?第三方工具通常很好,但是我想加深我对如何在.NET中编写表达式的理解。 我还需要确保不会对树进行评估,以便可以对数据库进行过滤。这意味着我需要制作一些实体框架4.0可以使用的东西。     

解决方法

我能想到的最接近的匹配是这样的:
public IQueryable<T> ApplyFilters(IQueryable<T> query)
{
    IQueryable<T> q;

    if (!Inclusive.Any())
        q = query;
    else
    {
        q = Enumerable.Empty<T>();
        Inclusive.ForEach(exp => q = q.Union(query.Where(exp)));
    }

    Exclusive.ForEach(exp => q = q.Where(exp));

    return q;
}
但是我几乎可以确定这将是非常低效的     ,尝试这样的事情? 我不确定我没有测试过。
Inclusive.ForEach(exp => q = q.Union(q.Where(exp)));
    ,即使已经有一个可接受的答案,我想指出的是,您可以使用谓词生成器将表达式与
Or
组合在一起。这会将其保留为对数据库的简单查询。 http://www.albahari.com/nutshell/predicatebuilder.aspx     ,我尚未在实体模型上对其进行测试,因此我不知道EF是否会支持它,但是以下适用于L2O。与Snowbear JIM编译器的代码仅稍有变化:
public IQueryable<T> ApplyFilters(IQueryable<T> query)
{
    Exclusive.ForEach(exp => query = query.Where(exp));

    if (Inclusive.Count == 0)
    {
        return query;
    }

    IQueryable<T> q = Enumerable.Empty<T>().AsQueryable<T>();
    Inclusive.ForEach(exp => q = q.Union(query.Where(exp)));

    return q;
}