2010-12-13 7 views
3

Ich bin sehr erfahren mit Expressions in .NET, deshalb frage ich euch lieber. Wie soll ich - siehe Kommentar unten:IQueryable <T>. Wo() passender Ausdruck wo?

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? 

Danke

+0

dies richtig zu verstehen - Sie wollen eine beliebig große Liste von Ausdrücken S nehmen und sie zusammen komponieren so das Ergebnis etwas wie ist: 'resultExpression = x => S [0] (x) || S [1] (x) || S [2] (x) ... || S [n] (x) '. Ist das richtig? –

Antwort

5

Sie können nicht „OR“ lambdas auf diese Weise zusammen. Sie möchten die Lambda-Körper wirklich "ODER" zusammen "OR". Hier ist eine Methode zu tun, dass:

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

Dann später:

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

Es ist eine Kombination von zwei Func<P, bool> auf Expressionsniveau.

Eine weniger Phantasie Art sein, das gleiche sollte tun:

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

Funktioniert für Func . Funktioniert nicht für Expression >. –

+0

@David B: Vielleicht wird ein Ausdruck überhaupt nicht benötigt. – VVS

1

Sie vielleicht einen kleinen Blick auf den Predicatebuilder nehmen wollen:

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

die Predicatebuilder ermöglichen es Ihnen, Englisch: www.mjfriendship.de/en/index.php?op...20&Itemid=32 Ich führe einige sehr mächtige Ausdrücke (AND/OR/NOT usw.) auf eine sehr saubere und leicht verständliche Weise auf. Für einfache Ausdrücke, ich natürlich tun rollen sie nur von Grund auf neu und gelten aber für die komplexe Sachen ...

Ich bin ein ziemlich Fan davon

ein paar Links auf SO :) selbst, sein kann hilfreich:

LINQ to SQL PredicateBuilder

Generated SQL with PredicateBuilder, LINQPad and operator ANY

0

.Where Methode nimmt als Parameter ein Lambda-Ausdruck, so dass Sie Ihre BinaryExpression auf eine komplette 012 bauen müssen.

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