Как я комбинирую выражения LINQ в одно?

У меня есть форма с несколькими полями на нем (название компании, почтовый индекс, и т.д.), который позволяет пользователю искать компании в базе данных. Если пользователь вводит значения больше чем в одно поле тогда, я должен искать на всех тех полях. Я использую LINQ для запросов базы данных.

До сих пор мне удалось записать функцию, которая посмотрит на их вход и превратит его в Список выражений. Я теперь хочу превратить тот Список в отдельное выражение, которое я могу тогда выполнить через поставщика LINQ.

Моя начальная попытка была следующие

private Expression<Func<Company, bool>> Combine(IList<Expression<Func<Company, bool>>> expressions)
    {
        if (expressions.Count == 0)
        {
            return null;
        }
        if (expressions.Count == 1)
        {
            return expressions[0];
        }
        Expression<Func<Company, bool>> combined = expressions[0];
        expressions.Skip(1).ToList().ForEach(expr => combined = Expression.And(combined, expr));
        return combined;
    }

Однако это перестало работать с сообщением об исключении вроде "Бинарного оператора И не определяется для...". У кого-либо есть какие-либо идеи, что я должен сделать для объединения этих выражений?

Править: Исправленный строка, где я забыл присваивать результат and'ing выражения вместе к переменной. Спасибо за указание на это люди.

19
задан gilles27 17 December 2009 в 15:53
поделиться

2 ответа

РЕДАКТИРОВАТЬ: ответ Джейсона теперь более полный, чем мой, с точки зрения материала дерева выражений, поэтому Я удалил этот бит. Однако я хотел оставить это:

Я полагаю, вы используете их для предложения Where ... почему бы просто не вызвать Where с каждым выражением по очереди? Это должно иметь тот же эффект:

var query = ...;
foreach (var condition in conditions)
{
    query = query.Where(condition);
}
9
ответ дан 30 November 2019 в 03:48
поделиться

Вы можете использовать Enumerable.Aggregate ] в сочетании с Expression.Also . Вот общая версия:

Expression<Func<T, bool>> AndAll<T>(
    IEnumerable<Expression<Func<T, bool>>> expressions) {

    if(expressions == null) {
        throw new ArgumentNullException("expressions");
    }
    if(expressions.Count() == 0) {
        return t => true;
    }
    Type delegateType = typeof(Func<,>)
                            .GetGenericTypeDefinition()
                            .MakeGenericType(new[] {
                                typeof(T),
                                typeof(bool) 
                            }
                        );
    var combined = expressions
                       .Cast<Expression>()
                       .Aggregate((e1, e2) => Expression.AndAlso(e1, e2));
    return (Expression<Func<T,bool>>)Expression.Lambda(delegateType, combined);
}

Ваш текущий код никогда не присваивается вместе :

expr => Expression.And(combined, expr);

возвращает новое выражение , которое является результатом побитового anding вместе и expr , но он не мутирует в сочетании .

25
ответ дан 30 November 2019 в 03:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: