Подтвердить что ты не робот

Динамические условия LINQ OR

Я хочу использовать LINQ для выполнения нескольких ситуаций, когда условия в коллекции похожи на

IEnumerable<Object> items;
items.Where(p => p.FirstName = "John");
items.Where(p => p.LastName = "Smith");

за исключением того, что вместо нескольких условий И (как в этом примере) я хотел бы иметь несколько условий ИЛИ.

ИЗМЕНИТЬ Извините, чтобы уточнить, я не знаю, сколько из этих условий у меня будет так

items.Where(p => p.FirstName = "John" || p => p.LastName = "Smith")

не будет работать.

В принципе, вот что я пытаюсь сделать:

foreach(var name in names)
{
    items = items.Where(p => p.Name == name);
}
4b9b3361

Ответ 1

Похоже, что ваш белый список имен известен только во время выполнения. Возможно, попробуйте следующее:

string[] names = new string[] {"John", "foo", "bar"};

var matching = items.Where(x => names.Contains(x.Name));

Ответ 2

Используйте PredicateBuilder:

Предположим, вы хотите написать запрос LINQ to SQL или Entity Framework, который реализует поиск по ключевому слову. Другими словами, запрос, который возвращает строки, описание которых содержит некоторый или весь заданный набор ключевых слов...

Идеальный подход состоит в том, чтобы динамически построить дерево лямбда-выражений, которое выполняет предикат на основе или.

Из всего, что побудит вас вручную создавать деревья выражений, потребность в динамических предикатах наиболее распространена в типичном бизнес-приложении. К счастью, его можно написать набор простых и многоразовых методов расширения, которые радикально упрощают эту задачу. Это роль нашего класса PredicateBuilder...

Ответ 3

Вы можете использовать .Union() для возврата результатов, удовлетворяющих любому условию.

var results = items.Where(p => p.FirstName == "John")
     .Union(items.Where(p => p.LastName == "Smith"));

Это хуже, чем оператор ||. Из вашего редактирования неясно, почему это не сработает.

Ответ 4

    public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
      this IEnumerable<Expression<Func<T, bool>>> filters)
    {
        Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault();
        if (firstFilter == null)
        {
            Expression<Func<T, bool>> alwaysTrue = x => true;
            return alwaysTrue;
        }

        var body = firstFilter.Body;
        var param = firstFilter.Parameters.ToArray();
        foreach (var nextFilter in filters.Skip(1))
        {
            var nextBody = Expression.Invoke(nextFilter, param);
            body = Expression.OrElse(body, nextBody);
        }
        Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param);
        return result;
    }

Затем, позже:

List<Expression<Func<Person, bool>>> filters = names
  .Select<string, Expression<Func<Person, bool>>>(name => 
    p => p.Name == name
  ).ToList();

Expression<Func<Person, bool>> filterOfOrs = filters.OrTheseFiltersTogether();

query = query.Where<Person>(filterOfOrs);

Ответ 5

Вы не можете сделать предложение Where динамическим, но вы можете динамически создавать выражение Lambda, которое вы передаете ему. Создайте правильный Expression, скомпилируйте его и передайте полученное лямбда-выражение в качестве параметра в предложение Where.

EDIT:

Хорошо, кажется, что вы можете пропустить часть, в которой вам нужно вручную создать выражение, и использовать PredicateBuilder для него, так как уже ответил AS-CII.