[英]Adding OR expressions in a loop in Linq
我有一個可變數量的OR條件,我想將它們放在一個Linq查詢中。
我怎么循環? 基本上,最終的查詢是:
IQueryable<MyObject> Q;
Q = Q.Where(q => (condition1) || (condition2) || ..... || (condition N));
就像是:
For (int i = 0; i < someNumber; i++) {
Q = Q.Where(q => (existing conditions) || (q.Value == i));
}
在沒有最終表達式(Q)的情況下,我可以使用什么語句來替換上面的示例(現有條件) ?
謝謝。
您需要構建一個表達您感興趣的所有條件的表達式樹,並結合Expression.OrElse
,然后在結束時調用Where
一次。
如果您當前的源是匿名類型,這可能有點棘手,但不應該太糟糕。 這是一個示例 - 可能有一種更簡單的方法來進行參數替換,但這並不算太糟糕。 (雖然ExpressionVisitor
僅適用於.NET 4 ...如果你想在.NET 3.5中使用它,你必須自己實現類似的東西。)
using System;
using System.Linq;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
IQueryable<string> strings = (new[] { "Jon", "Tom", "Holly",
"Robin", "William" }).AsQueryable();
Expression<Func<string, bool>> firstPredicate = p => p.Contains("ll");
Expression<Func<string, bool>> secondPredicate = p => p.Length == 3;
Expression combined = Expression.OrElse(firstPredicate.Body,
secondPredicate.Body);
ParameterExpression param = Expression.Parameter(typeof(string), "p");
ParameterReplacer replacer = new ParameterReplacer(param);
combined = replacer.Visit(combined);
var lambda = Expression.Lambda<Func<string, bool>>(combined, param);
var query = strings.Where(lambda);
foreach (string x in query)
{
Console.WriteLine(x);
}
}
// Helper class to replace all parameters with the specified one
class ParameterReplacer : ExpressionVisitor
{
private readonly ParameterExpression parameter;
internal ParameterReplacer(ParameterExpression parameter)
{
this.parameter = parameter;
}
protected override Expression VisitParameter
(ParameterExpression node)
{
return parameter;
}
}
}
一個不太優化的版本(祈禱后端將進行必要的提升和優化)。
public static IQueryable<T> Any<T>(this IQueryable<T> q,
params Expression<Func<T, bool>>[] preds)
{
var par = Expression.Parameter(typeof(T), "x");
Expression body = Expression.Constant(false);
foreach (var pred in preds)
{
body = Expression.OrElse(body, Expression.Invoke(pred, par));
}
var ff = Expression.Lambda(body, par) as Expression<Func<T, bool>>;
return q.Where(ff);
}
static void Main(string[] args)
{
var q = new[] { "jim", "bob", "Jon", "leppie" }.AsQueryable();
Expression<Func<string, bool>>[] preds =
{
x => x == "Jon",
x => x == "Skeet",
x => x == "leppie"
};
var result = q.Any(preds).ToArray();
}
public static IEnumerable<T> GetItemsThatMatchAny<T> (this IEnumerable<T> source, IEnumerable<Func<T,bool>> predicates)
{
return source.Where(t => predicates.Any(predicate => predicate(t)));
}
謂詞生成器的示例:
private static IEnumerable<Func<MyClass, bool>> GetPredicates (int num)
{
var predicates = new Func<MyClass, bool>[] {m => m.Foo == 3, m => m.Bar =="x", m => DateTime.Now.DayOfWeek == DayOfWeek.Sunday};
return predicates.Take (num);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.