2010-03-01 22 views
8
Katılma

Ben Postadölesan gibi iki lambda ifadeleri katılma hakkında giderdim nasıl böyle bir ifadenin içine ...lambda İfadeler

Expression<Func<string, bool>> expr1 = a => a.Length > 100; 
Expression<Func<string, bool>> expr2 = b => b.Length < 200; 

: Bir AndAlso operatör ile bunları birleştiren olduğunu

Expression<Func<string, bool>> expr3 = s => s.Length < 100 && s.Length < 200; 

. (Veya bu konuyla ilgili başka bir operatör ...)

Aslında lambda parametrelerinin bazı kötü yinelemeli replasmanını gerçekleştirdikten sonra Expression.AndAlso yöntemiyle birleştim. Ama daha basit bir şey arıyorum. gibi

Örneğin şey: (. Açıkçası çalışmıyor Hangi)

Expression<Func<string, bool>> expr3 = c => expr1(a) && expr2(b); 
+0

Sadece merak neden kullandığınız can İfade > expr3 = s => s.Length <100 && s.Length <200 ;? –

+0

Bunun nedeni, ifadelerin sistemdeki ayarlara bağlı olarak üretilmesidir. Aslında bir son ifadeye bir ifade listesi katılmaya ihtiyacım var. – LaZe

cevap

2

normal temsilciler ile mücadele olsaydı çalışacak Sizin "gibi bir şey". Ancak ifade ağaçları kullanmanız gerekiyorsa, yinelemeli değiştirmeden başka bir çözüm göremiyorum.

.NET 4'te, bu tür yinelemeli değiştirme işlemini daha kolay hale getirmek için System.Linq.Expressions.ExpressionVisitor'ı kullanabilirsiniz. .NET 3.5 için, bu örnekte bir bakın: http://msdn.microsoft.com/en-us/library/bb882521.aspx

ExpressionVisitor'ı kullanarak, değiştirmek istediğiniz düğüm türleri için yöntemleri geçersiz kılmanız ve çevreleyen ağacın otomatik olarak yeniden yapılandırılması gerekir.

LINQ ile kullanım koşullarını ele alıyorsanız, koşulları dinamik olarak birleştirmek için çok daha kolay bir çözüm, birden çok kez Where() öğesini çağırmaktır.

+0

Sadece kontrol ettim ve ExpressionVisitor bunun için harika çalışıyor. 4.0 için serbest bırakılması zor olabilir. – LaZe

1

Bunu yeni bir Güncelleştirme yöntemini kullanarak .NET 4 ile nasıl yapılacağını keşfettim. Yeni bir yöntem olduğu için, buna ihtiyaç duyduklarını düşünüyorum. Bunun için gerçekten çok mutluyum çünkü med. NET 3.5 çözümü gerçekten çirkin. (NOT:. Bu çözüm yine de işe yorumlara göz atın etmez.)

Expression<Func<string, bool>> expr1 = a => a.Length > 100; 
Expression<Func<string, bool>> expr2 = b => b.Length < 200; 

// This produces a new expression where the parameter b is replaced with a 
expr2 = expr2.Update(expr1.Body, expr1.Parameters); 

// So now we can join the bodies and produce a new lambda expression. 
Expression<Func<string, bool>> expr3 = Expression.Lambda<Func<string, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters); 
+0

Güncellemenin ne yaptığını yanlış anlıyorsunuz. Sadece aynı tip, isim ve tailcall seçenekleriyle yeni bir LambdaExpression oluşturur, ancak farklı bir gövde ve parametre seti ile. Lamdba gövdelerinde herhangi bir değişiklik yapmaz. Örnek kod çıkışlarınızı çalıştırma "a => ((a.Length> 100) VeAlso (a.Length> 100))" expr3 için, istediğiniz gibi değil. – Daniel

+0

Ne yazık ki siz Daniel haklısınız ... bu yüzden benim kötü çözümüme geri döndüm :-( – LaZe

2

O Expression.Invoke ile çok kötü değil ...:

var strings = (new [] { "a", "bb", "ccc", "dddd", "eeeee", "fffff" }); 
Expression<Func<string, bool>> expr1 = a => a.Length > 1; 
Expression<Func<string, bool>> expr2 = b => b.Length < 4; 

ParameterExpression p = expr1.Parameters[0]; 

var andAlso = System.Linq.Expressions.Expression.AndAlso(Expression.Invoke(expr1, p), Expression.Invoke(expr2, p)); 
var lambda = LambdaExpression.Lambda<Func<string, bool>>(andAlso, p); 
var filteredStrings = strings.AsQueryable().Where(lambda); 
+0

Öneriniz için teşekkürler Richard. Bu fikre bakacağım. İfadeleri SQL'e dönüştürdüğümden (diğer şeyler arasında) Ben ' Benim sistemde InvokeExpression çeşitli yerlerde destek gerekir.Fakat şimdiki çözümden daha güzel ... – LaZe

+0

Ben sadece bu biraz önce vardı ve tamamen sıkışmış bir sorunu çözmek yardımcı olabilir anladım .... Şerefe! –