Создайте лямбда-выражение из списка, где каждый элемент является OR’ed

#c# #lambda

#c# #лямбда

Вопрос:

Я не уверен, возможно ли это вообще, но следующий код работает:

 searchDescriptor.Query(q => firstQuery || secondQuery || thirdQuery);
  

Но я передал их в свой метод из списка myOrQueries, поэтому мне нужно сделать что-то вроде:

 List<Query> myOrQueries; // includes the 3 items above

// what I need is the correct way of doing the line below - if possible??
searchDescriptor.Query(q => myOrQueries[0] || myOrQueries[1] || myOrQueries[2]);
  

Возможно ли каким-либо образом выбрать каждый элемент и ИЛИ его?

Комментарии:

1. Вы имеете в виду объединение?

2. Нет, так не думаю. Мне нужно иметь возможность делать что-то вроде: q => myOrQueries.ForEach(||) или подобное. В основном OR’ing список.

Ответ №1:

Ну, умный поставщик LINQ сможет работать с массивом напрямую, что-то вроде этого:

 searchDescriptor.Query(q => myOrQueries.Any())
  

Если этого недостаточно, вам просто нужно объединить эти запросы вместе с помощью OrElse и использовать их как единый предикат в Where исходном searchDescriptor.

Это немного длинновато, поэтому я просто отсылаю вас к PredicateBuilder вспомогательному классу Джо Альбахари:http://www.albahari.com/nutshell/predicatebuilder.aspx

Это помогает добавлять их в качестве методов расширения IQueryable , они довольно удобны 🙂

Редактировать:

Простое решение, которое работает:

 BaseQuery variableQuery = null;

if (roleStatuses != null amp;amp; roleStatuses.Any())
{
  foreach (string roleStatus in roleStatuses)
  {
    var status = roleStatus;
    var subQuery = 
        new QueryDescriptor<MySearchDataContract>()
        .Match(s => s.OnField(o => o.Roles.First().RoleStatus)
                     .QueryString(status));

    variableQuery = variableQuery == null ? subQuery : variableQuery || subQuery;
  }
}
  

Комментарии:

1. Any будет проверяться только то, что в списке что-то есть, предполагая, что каждый элемент является фактическим запросом, тогда их, вероятно, потребуется выполнить, например Any(x => x()) .

2. searchDescriptor.Query(q => myOrQueries.Any()) будет соответствовать каждому элементу до тех пор, myOrQueries пока есть хотя бы один элемент. Это должно быть searchDescriptor.Query(q => myOrQueries.Any(x => x(q))

3. Ну, я понятия не имею, что это за запросы, поэтому я не могу написать «полностью правильный» код, я просто излагаю рассуждения. Скорее всего, что-то вроде searchDescriptor.Query(q => possibleValues.Contains(q.SomeField) будет лучше.

4. @Luaan Я думаю, проблема в том, что вы предполагаете, что Any это должно просто «работать», когда на самом деле все Any определяет, что в списке есть что -то, это никоим образом не оценивает значение этого конкретного элемента в списке (что и ищет OP).

5. .Any() — это не то, что я ищу. Смотрите мою первую строку (которая работает) — мне нужно получить тот же результат, используя список. Я попробую PredicateBuilder и дам вам знать. Спасибо

Ответ №2:

Благодаря комментариям от Luaan — лямбда была недоступна, но простой способ построить выражение работает:

 BaseQuery variableQuery = null;

if (roleStatuses != null amp;amp; roleStatuses.Any())
{
  foreach (string roleStatus in roleStatuses)
  {
    var status = roleStatus;
    var subQuery = new QueryDescriptor<MySearchDataContract>()
                          .Match(s => s.OnField(o => o.Roles.First().RoleStatus)
                          .QueryString(status));

    variableQuery = variableQuery == null ? subQuery : variableQuery || subQuery;
  }
}