动态添加或条件

时间:2018-01-26 17:27:23

标签: c# linq .net-4.6

我有一个集合,我想以编程方式向LINq查询添加OR条件。我知道如何添加如下的AND条件:

var mySet = SomeFactory.GetData();
foreach(var nameFilter in nameFilters)
{
  mySet = mySet.Where(item => item.Name == nameFilter);
}
foreach(var ageFilter in ageFilters)
{
  mySet = mySet.Where(item => item.Age == ageFilter)
}

然而,如果我希望这些是OR条件而不是'AND'在一起,我该怎么做? I.E.如果我知道我将永远同时拥有两个不同的值,我就能做到这一点:

mySet.Where(item => item.Name == nameFilter[0] || item.Name == nameFilter[1] ...  || item.Age == ageFilter[0] || item.Age == ageFilter[1] || ...);

TL; DR:我希望能够将未知数量的布尔检查链接到使用OR语句计算的单个表达式中。例如,如果我有一个名为Mary或Jim的人的交叉引用,他们是32或51。

2 个答案:

答案 0 :(得分:1)

PredicateBuilder可以帮助您在灵活性中应用where子句。您可以找到扩展方法here

var filterOfNames = new List<string> {"Sample", "Sample2"};
var filterOfAges = new List<int> { 21, 33, 45 };
var mySet = SomeFactory.GetData();
var predicate = PredicateBuilder.True<TypeOfmySet>();
foreach (var filterOfName in filterOfNames)
{
    //If it is the first predicate, you should apply "And"
    if (predicate.Body.NodeType == ExpressionType.Constant)
    {
        predicate = predicate.And(x => x.Name == filterOfName);
        continue;
    }
    predicate = predicate.Or(x => x.Name == filterOfName);
}
foreach (var filterOfAge in filterOfAges)
{
    //If it is the first predicate, you should apply "And"
    if (predicate.Body.NodeType == ExpressionType.Constant)
    {
        predicate = predicate.And(x => x.Age == filterOfAge);
        continue;
    }
    predicate = predicate.Or(x => x.Age == filterOfAge);
}
//I don't know the myset has which type in IQueryable or already retrieved in memory collection. If it is IQueryable, don't compile the predicate otherwise compile it.
//var compiledPredicate = predicate.Compile();
mySet = mySet.Where(predicate);

答案 1 :(得分:0)

LINQ中没有添加剂“或”。组合“Where”表达式始终被评估为“和”。

但是,您可以构建谓词,将它们添加到列表中,然后测试它们。我认为这段代码可以满足您的需求:

using System;
using System.Collections.Generic;

class Item
{
    internal string Name { get; set; }
    internal short Age { get; set; }
    internal string City { get; set; }
}
public static class ExtensionMethods
{
    public static List<T> FindAll<T>(this List<T> list, List<Predicate<T>> predicates)
    {
        List<T> L = new List<T>();
        foreach (T item in list)
        {
            foreach (Predicate<T> p in predicates)
            {
                if (p(item)) L.Add(item);
            }
        }
        return L;
    }
}
class Program
{
    static void Main(string[] args)
    {
        List<Item> items = new List<Item>();
        items.Add(new Item { Name = "Bob", Age = 31, City = "Denver" });
        items.Add(new Item { Name = "Mary", Age = 44, City = "LA" });
        items.Add(new Item { Name = "Sue", Age = 21, City = "Austin" });
        items.Add(new Item { Name = "Joe", Age = 55, City = "Redmond" });
        items.Add(new Item { Name = "Tom", Age = 81, City = "Portland" });

        string nameFilter = "Bob,Mary";
        //string ageFilter = "55,21";
        string ageFilter = null;
        string cityFilter = "Portland";

        List<Predicate<Item>> p = new List<Predicate<Item>>();

        if (nameFilter != null)
        {
            p.Add(i => nameFilter.Contains(i.Name));
        }

        if (cityFilter != null)
        {
            p.Add(i => cityFilter.Contains(i.City));
        }

        if (ageFilter != null)
        {
            p.Add(i => ageFilter.Contains(i.Age.ToString()));
        }

        var results = items.FindAll(p);

        foreach (var result in results)
        {
            Console.WriteLine($"{result.Name} {result.Age} {result.City}");
        }
    }
}