如何将viewmodel修改为Expression <Func <T,bool >>?

Sam*_*Sam 0 c# ienumerable iqueryable func expression-trees

捎带一个非常相似的问题 ......

我需要从ViewModel生成一个表达式作为搜索谓词传递.我需要能够根据用户提供的内容包含/排除查询参数.例:IQueryable.Where

public class StoresFilter
{
    public int[] Ids { get; set; }

    [StringLength(150)]
    public string Name { get; set; }

    [StringLength(5)]
    public string Abbreviation { get; set; }

    [Display(Name = "Show all")]
    public bool ShowAll { get; set; } = true;

    public Expression<Func<Store, bool>> ToExpression()
    {
        List<Expression<Func<Store, bool>>> expressions = new List<Expression<Func<Store, bool>>>();

        if (Ids != null && Ids.Length > 0)
        {
            expressions.Add(x => Ids.Contains(x.Id));
        }
        if (Name.HasValue())
        {
            expressions.Add(x => x.Name.Contains(Name));
        }
        if (Abbreviation.HasValue())
        {
            expressions.Add(x => x.Abbreviation.Contains(Abbreviation));
        }
        if (!ShowAll)
        {
            expressions.Add(x => x.Enabled == true);
        }
        if (expressions.Count == 0)
        {
            return x => true;
        }

        // how to combine list of expressions into composite expression???
        return compositeExpression;
    }
}
Run Code Online (Sandbox Code Playgroud)

有一种简单的方法可以从表达式列表中构建复合表达式吗?或者我需要经历的过程中采用人工制作的表情ParameterExpression,Expression.AndAlso, ExpressionVisitor,等?

Sla*_*nov 7

你不应该构建和组合Expressions,但是你应该通过IQuerable<Store>via .Wherechain 来实现它.而且,source.Expression将包含所需的表达式:

public IQueryable<Store> ApplyFilter(IQueryable<Store> source)
{
    if (Ids != null && Ids.Length > 0)  
        source = source.Where(x => Ids.Contains(x.Id)); 

    if (Name.HasValue())    
        source = source.Where(x => x.Name.Contains(Name));  

    if (Abbreviation.HasValue())    
        source = source.Where(x => x.Abbreviation.Contains(Abbreviation));  

    if (!ShowAll)   
        source = source.Where(x => x.Enabled == true);      

    //or return source.Expression as you wanted
    return source;
}
Run Code Online (Sandbox Code Playgroud)

用法:

var filter = new StoresFilter { Name = "Market" };
var filteredStores = filter.ApplyFilter(context.Stores).ToList();
Run Code Online (Sandbox Code Playgroud)