2010-12-13 77 views
3

Je suis très faible expérience avec Expressions dans .NET, c'est pourquoi je vous demande plutôt les gars. Comment dois-je - voir le commentaire ci-dessous:IQueryable <T>. Où() expression appropriée dans où?

using P = Myclass; 
.. 
System.Linq.Expressions.Expression<Func<P, bool>> myExpression = null; 
.. 
myExpression1 = x => foo1 == true && foo2 == false; 
myExpression2 = x => ... ; 
.. 
BinaryExpression resultExpression = System.Linq.Expressions.Expression.OrElse(myExpression1, myExpression2); 
.. 
IQueryable<P> l = l.Where(?resultExpression?); // how to transform BinaryExpression to the suitable type? 

Merci

+0

Pour comprendre cela correctement - Vous voulez prendre une liste des expressions S arbitrairement taille et de les composer ensemble de sorte que le résultat est quelque chose comme: 'resultExpression = x => S [0] (x) || S [1] (x) || S [2] (x) ... || S [n] (x) '. Est-ce correct? –

Répondre

5

Vous ne pouvez pas « OU » lambdas ensemble de cette façon. Vous voulez vraiment "OU" les corps lambda ensemble. Voici une méthode pour le faire:

public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>( 
    this IEnumerable<Expression<Func<T, bool>>> filters) 
{ 
    Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault(); 
    if (firstFilter == null) 
    { 
     Expression<Func<T, bool>> alwaysTrue = x => true; 
     return alwaysTrue; 
    } 

    var body = firstFilter.Body; 
    var param = firstFilter.Parameters.ToArray(); 
    foreach (var nextFilter in filters.Skip(1)) 
    { 
     var nextBody = Expression.Invoke(nextFilter, param); 
     body = Expression.OrElse(body, nextBody); 
    } 
    Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param); 
    return result; 
} 

Puis, plus tard:

Expression<Func<P, bool>> myFilter1 = x => foo1 == true && foo2 == false; 
Expression<Func<P, bool>> myFilter2 = x => ... ; 
.. 
List<Expression<Func<P, bool>>> filters = new List<Expression<Func<P, bool>>>(); 
filters.Add(myfilter1); 
filters.Add(myfilter2); 
.. 
Expression<Func<P, bool>> resultFilter = filters.OrTheseFiltersTogether(); 
IQueryable<P> query = query.Where(resultFilter); 
-2

Sa combinaison de deux Func<P, bool> au niveau d'expression.

Une façon moins fantaisie de faire la même chose devrait être:

Func<P, bool> myExpression1 = x => foo1 == true && foo2 == false; 
Func<P, bool> myExpression2 = x => ... ; 

IQueryable<P> l = l.Where((p) => myExpression1(p) || myExpression2(p)); 
+1

Fonctionne pour Func . Ne fonctionne pas pour Expression >. –

+0

@David B: Peut-être qu'une expression n'est pas nécessaire du tout. – VVS

1

vous pourriez vouloir jeter un oeil petit au PredicateBuilder:

http://www.albahari.com/nutshell/predicatebuilder.aspx

le PredicateBuilder vous permet de lancer des expressions très puissantes (AND/OR/NOT etc, etc) d'une manière très propre et facile à comprendre. Pour les expressions simples, je fais bien sûr simplement les rouler à partir de zéro et d'appliquer, mais pour les choses complexes ...

Je suis assez fan de celui-ci :)

quelques liens sur lui-même qui peut être utile:

LINQ to SQL PredicateBuilder

Generated SQL with PredicateBuilder, LINQPad and operator ANY

0

méthode .Where prend une expression lambda comme paramètre, vous devez construire votre BinaryExpression à une 012 complète.

var resultExpression = Expression.OrElse(myExp1, myExp2); 
    // now the exp is like: p > 100 || p < 10 
ParameterExpression parameterExp = Expression.Parameter(typeof(P),"p"); 
    // construct a parameter with its type P, looks like: p => 
LambdaExpression lambdaExp = Expression.Lambda(resultExpression, parameterExp); 
    // merge the two expressions: p => p > 100 || p < 10 
myList.Where(lambdaExp.Compile());