C# 动态添加或修改条件

C# 动态添加或修改条件,c#,linq,.net-4.6,C#,Linq,.net 4.6,我有一个集合,希望通过编程向linq查询添加或条件。我知道如何添加以下条件: 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 => it

我有一个集合,希望通过编程向linq查询添加或条件。我知道如何添加以下条件:

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)
}
然而,如果我希望这些条件是或是,而不是“和”在一起,我会怎么做呢?也就是说,如果我知道我将始终同时拥有这两个值,并且永远不会拥有不同值的数组,那么我可以做到这一点:

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岁的交叉引用。

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

var filterOfNames=新列表{“Sample”,“Sample2”};
var filterOfAges=新列表{21,33,45};
var mySet=SomeFactory.GetData();
var predicate=PredicateBuilder.True();
foreach(filterOfNames中的变量filterOfName)
{
//如果它是第一个谓词,则应应用“And”
if(predicate.Body.NodeType==ExpressionType.Constant)
{
谓词=谓词和(x=>x.Name==filterOfName);
继续;
}
谓词=谓词。或(x=>x.Name==filterOfName);
}
foreach(filterOfAges中的变量filterOfAges)
{
//如果它是第一个谓词,则应应用“And”
if(predicate.Body.NodeType==ExpressionType.Constant)
{
谓词=谓词和(x=>x.Age==filterOfAge);
继续;
}
谓词=谓词或(x=>x.Age==filterOfAge);
}
//我不知道myset在IQueryable中有哪种类型,或者已经在内存集合中检索到了哪种类型。如果它是IQueryable,不要编译谓词,否则就编译它。
//var compiledPredicate=predicate.Compile();
mySet=mySet.Where(谓词);
LINQ中没有添加剂“或”。组合“Where”表达式的计算结果始终为“and”

但是,您可以构建谓词,将它们添加到列表中,然后测试它们。我认为此代码符合您的要求:

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}");
        }
    }
}
使用系统;
使用System.Collections.Generic;
类项目
{
内部字符串名称{get;set;}
内部短时间{get;set;}
内部字符串City{get;set;}
}
公共静态类扩展方法
{
公共静态列表FindAll(此列表,列表谓词)
{
列表L=新列表();
foreach(列表中的T项)
{
foreach(谓词中的谓词p)
{
如果(p(项目))L.添加(项目);
}
}
返回L;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
列表项=新列表();
添加(新项目{Name=“Bob”,年龄=31,City=“Denver”});
添加(新项目{Name=“Mary”,年龄=44,City=“LA”});
添加(新项目{Name=“Sue”,年龄=21,City=“Austin”});
添加(新项目{Name=“Joe”,年龄=55,City=“Redmond”});
添加(新项目{Name=“Tom”,年龄=81,City=“Portland”});
字符串nameFilter=“Bob,Mary”;
//字符串ageFilter=“55,21”;
字符串ageFilter=null;
字符串cityFilter=“波特兰”;
列表p=新列表();
if(nameFilter!=null)
{
p、 添加(i=>nameFilter.Contains(i.Name));
}
if(cityFilter!=null)
{
p、 添加(i=>cityFilter.Contains(i.City));
}
if(ageFilter!=null)
{
p、 添加(i=>ageFilter.Contains(i.Age.ToString());
}
var结果=项目。FindAll(p);
foreach(结果中的var结果)
{
WriteLine($“{result.Name}{result.Age}{result.City}”);
}
}
}

什么是名称过滤器?单个值、逗号分隔的值等?它是一个字符串。。。对不起,这个例子太可怕了。让我调整一下问题谢谢,我看到这对我的内存对象有效,但我目前正试图将其与LinqToSalesforce结合使用,但未能对其进行评估。回到绘图板上。如果这个库实现了contains方法,我的解决方案将非常简单。感谢您的帮助。请参阅我的解决方案,使用contains。在最后一行中,当您将谓词放入“Where”中时,可能需要编译生成的表达式:
mySet.Where(predicate.compile())
基于此的解决方案:
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}");
        }
    }
}