2010-08-11 2 views
13

변수 번호가 또는이고 하나의 Linq 쿼리에 넣고 싶습니다.Linq 루프에서 OR 식 추가하기

루프에서 어떻게 수행합니까?

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)를 예 (기존 조건)을 대체하는 데 사용할 수있는 어떤 문 Q를 내부에 중첩 시켰습니까?

감사합니다.

답변

16

관심있는 모든 조건을 나타내는 표현 트리를 작성하고 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; 
     } 
    } 
} 
+0

내가 필요로하는 것 : D –

+0

Replacer는 정확히 무엇을하고 있습니까? – seebiscuit

+0

@Seisciscuit : 기본적으로 결과 표현식 트리의 모든 매개 변수 표현식은 최상위 레벨과 각각의 "하위 표현식"에 대해 별도의 매개 변수 표현식을 갖기보다는 동일한 매개 변수 표현식을 참조합니다. –

2
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); 
} 
+0

비슷한 아이디어가 있지만 불행히도 Linq2Sql에서는 실패합니다. – leppie

+1

네, 맞습니다. IQueryable 비트가 누락되었습니다. – Ani

2

최적화되지 않은 버전입니다 (백엔드가 필요한 리프팅 및 최적화를 수행하도록기도하십시오).

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(); 
} 
+0

linq ro 엔티티에서 작동하지 않습니다. – moyomeh