2010-12-11 26 views
17

IQueryable sıralarını süzmek için kullanılan bir ifadeyi devre dışı bırakmanın bir yolunu arıyorum. bu yüzden temelde expression olumsuzlamak istiyorum -C# bir ifade reddetme

Expression<Func<T, bool>> expression = (x => true); 

Şimdi (x => false) elde yol açacağı ifade oluşturmak isteyen: gibi

Yani, var bir şey.

var negatedExpression = 
    Expression.Lambda<Func<T, bool>> (Expression.Not(expression.Body), 
            expression.Parameters[0]))); 

Ama daha iyi bir yol yoktur neredeyse eminim - bana yardım edebileceğini:

çalışma yöntemi buldum kendimi bu gibi çalışır? (muhtemelen Not(expression) gibi bir şey).

cevap

17

kolay bir uzantısı yöntemi:

public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> one) 
{ 
    var candidateExpr = one.Parameters[0]; 
    var body = Expression.Not(one.Body); 

    return Expression.Lambda<Func<T, bool>>(body, candidateExpr); 
} 

Kullanım: ileride kullanmak üzere

Expression<Func<int, bool>> condition = x => x > 5; 
var source = Enumerable.Range(1, 10); 
var result1 = source.Where(condition.Compile()); //6,7,8,9,10 
var result2 = source.Where(condition.Not().Compile()); //1,2,3,4,5 
+0

Eh, bir 'Not' yöntemine bir ifadeyi reddetmek için yolumuzu nasıl sarmak bilmiyorum, ama aslında aslında olumsuzluk gerçekleştirmek için kolay bir yol arıyordum * (bana Expression.Lambda çağıran bakın). Blablabla 'büyük bir overkill). * –

+2

İfade Ağaçlar değişmez, bu yüzden yeni bir lambda oluşturmanız gerekir. –

-2

Buna ne dersiniz?

Expression<Func<bool>> expr =() => true; 
Expression<Func<bool>> negated =() => !expr.Compile()(); 
+0

Girdi ifadesini opak yöntem çağrısı haline getirdiniz. Bu, bir ifade kullanmanın amacı, sağlanan sorgulamanın bunu anlayabildiğinden bu yana hiçbir şekilde yardımcı olmaz. – CodesInChaos

1

Gönderme.

Danny Chen'in cevabı daha genel yapılabilir:

public static Expression<TFunc> Not<TFunc>(this Expression<TFunc> baseExpr) 
{ 
    var param = baseExpr.Parameters; 
    var body = Expression.Not(baseExpr.Body); 
    var newExpr = Expression.Lambda<TFunc>(body, param); 
    return newExpr; 
} 

Bu sürüm giriş parametreleri herhangi bir sayı ile bir Expression alabilirsiniz. Bununla birlikte, İfade'nin büyük olasılıkla IEnumerable.Where gibi bir işleve geçmesi büyük olasılıkla biraz kullanım kolaylığı sağlar.