Создание ContainsAny и ContainsAll расширений - PullRequest
0 голосов
/ 24 мая 2011

Я пытаюсь создать расширение ContainsAny и ContainsAll, чтобы я мог в основном сделать следующее

string[] words = keywords.split(' ');

from c in comments
where c.Text.ContainsAny(words)
select c

до сих пор мне удалось сделать следующее:

У меня есть эти два расширения для ands и ors

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) {
            var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
            return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
        }

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) {
                var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
                return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
            }

и тогда у меня есть:

Expression<Func<Entities.Comment, bool>> predicate = c => false;
        foreach (string word in query.Split(' ')) {
            string w = word;
            predicate = predicate.Or(c => c.Text.Contains(w));
        }

        q = q.Where(predicate);

Теперь все это прекрасно работает, но я не уверен, как извлечь эту функциональность в универсальное расширение, которое я могу затем использовать против любого объекта.

Любая помощь будет наиболее ценной

Ответы [ 3 ]

1 голос
/ 26 мая 2011

Вопрос не на 100% ясен.Мне кажется, что вы пытаетесь реализовать в Linq общий предикат ContainsAll / ContainsAny, который вы будете использовать в предложении 'where', поэтому мои реализации основаны на этом предположении.

Я быреализовать эти простые методы расширения в IEmumerable:

    public static bool ContainsAny<T>(this IEnumerable<T> sequence, params T[] matches)
    {
        return matches.Any(value => sequence.Contains(value));
    }

    public static bool ContainsAll<T>(this IEnumerable<T> sequence, params T[] matches)
    {
        return matches.All(value => sequence.Contains(value));
    }

таким образом, вы можете вызвать:

from c in comments
where (
       c.Text.ContainsAny("A", "B") ||
       c.Text.ContainsAll("X", "Y"))
select c

(т.е. выбрать комментарии, содержащие «A» ИЛИ «B» или (не исключая), содержащиеоба "X" и "Y")

1 голос
/ 24 мая 2011
public static IQueryable<T> ContainsAny<T>(this IQueryable<T> q, Expression<Func<T, string>> text, params string[] items)
{
    Expression<Func<T, bool>> predicate = c => false;
    var contains = typeof (String).GetMethod("Contains");
    foreach (var item in items)
    {
        var containsExpression = Expression.Call(text.Body, contains, Expression.Constant(item, typeof (String)));
        var lambda = Expression.Lambda<Func<T, bool>>(containsExpression, text.Parameters);
        predicate = predicate.Or(lambda);
    }

    return q.Where(predicate);
}

теперь можно звонить

comments.ContainsAny(x => x.Text, words);

или

comments.ContainsAny(x => x.Text, "a", "b");
0 голосов
/ 25 апреля 2012

// реализация содержащего все против набора ключевых слов

public static bool содержитAll (это строковое описание, строка [] ключевые слова) {

        List<string> list = new List<string>();// new collection

        string[] descriptionArray = description.Split(' ').Select(i => i).ToArray(); 

        foreach (string s in keywords) 
             { if (descriptionArray.Contains(s)) { list.Add(s); 
                   } }
        if (list.Count == keywords.Length) { return true; } return false;
    }

// реализация методов ContainsAny ()

публичный статический bool содержитAny (это строковое описание, строка [] ключевые слова) {

        List<string> list = new List<string>();

        string[] descriptionArray = description.Split(' ').Select(i => i).ToArray();

        foreach (string s in keywords)
              { if (descriptionArray.Contains(s)) { list.Add(s); } }

        if (list.Count == 0) { return true; } return false;
    }
...