2011-05-24 127 views
0

我試圖創建一個ContainsAny和ContainsAll擴展,所以我可以基本上做到以下創建ContainsAny和ContainsAll擴展

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

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

到目前爲止,我已經成功地做到以下幾點:

我有這些兩個擴展爲AND和OR值爲

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); 

現在,這一切工作正常,但我不知道如何將此功能提取到一個通用的擴展,然後我可以使用任何對象。

任何幫助將非常感激

回答

1
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

感謝您的回答,但我不確定這會解決我的問題。我上面應該提到的是,我希望能夠做到:從c中的註釋中,c.text.containsAny(words)|| c.text.containsAll(words) – Gazeth 2011-05-25 12:23:59

+0

我想這是可能的,但那肯定會更復雜。無論如何..使用上面的例子做的伎倆,只是不同的語法 – maxlego 2011-05-25 14:51:23

1

的問題是不是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」)

0

//實現containsAll針對關鍵字集合

公共靜態布爾containsAll(此字符串的描述中,串[]關鍵字){

 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()方法

公共靜態布爾containsAny(此字符串的描述中,串[]關鍵字){

 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; 
    }