Projelerde bazı koşullara göre değişiklik gösteren durumlar olabilir. Bir lambda ifadesine farklı durumlar için istediğimiz bir lambda ifadesini ekleyerek sonuç almak isteyebiliriz.
Veritabanında isme göre bir filtreleme yapmak istediğimizi düşünelim. Bu durumda isteğe göre birçok farklı ifade ortaya çıkacaktır.
Aşağıdaki örnekte bir kişi listesinden “m” ve “e” harflerini içeren isimleri filtrelemek istiyoruz.
Bu durumda şöyle birşey de söyleyebiliriz;
Hem “m” hem de “e” harflerini tek bir lambda ifadesi içerisinde de belirtebiliriz.
List<string> names = new List<string> { "Serhat", "Mehmet", "Gizem", "Hasan", "Ayşe", "Cemal", "Melis" };
var result = names.Where(x => x.Contains("m") && x.Contains("e"));
Bu doğru ancak bizim istediğimiz şey ilk olarak bir lambda ifadesi belirtmek ve bunu yaptıktan sonra farklı bir lambda ifadesi ile bunu birleştirmek.
Şimdi ExpressionExtensions ve ReplaceExpressionVisitor sınıflarını ekleyelim ve işlemleri gerçekleştirelim.
public static class ExpressionExtensions
{
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var parameter = Expression.Parameter(typeof(T));
var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter);
var left = leftVisitor.Visit(expr1.Body);
var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter);
var right = rightVisitor.Visit(expr2.Body);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), parameter);
}
}
public class ReplaceExpressionVisitor : ExpressionVisitor
{
private readonly Expression _oldValue;
private readonly Expression _newValue;
public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
{
_oldValue = oldValue;
_newValue = newValue;
}
public override Expression Visit(Expression node)
{
if (node == _oldValue)
return _newValue;
return base.Visit(node);
}
}
List<string> values = new List<string> { "Serhat", "Mehmet", "Gizem", "Hasan", "Ayşe", "Cemal", "Melis" };
Expression<Func<string, bool>> filter1;
Expression<Func<string, bool>> filter2;
filter1 = x => x.Contains("m");
filter2 = x => x.Contains("e");
var combined = ExpressionExtensions.AndAlso(filter1, filter2);
var compiled = combined.Compile();
var result1 = values.Where(compiled);
Yukarıda ilk olarak bir liste tanımladık ve içerisine isimler ekledik.
Ardından iki ayrı lambda ifadesi tanımlayarak bunları ExpressionExtensions metodu ile birleştirdik.
Birleştirdiğimiz ifadeler sonuç olarak Expression<Func<string,bool>> tipinde dönmektedir. Bu sonucu compile() metodu ile Func<string,bool> tipine dönüştürürüz.
Son olarak elde ettiğimiz delegeyi Where() metodu içerisine ekleyerek istediğimiz sonucu elde ederiz
ExpressionExtensions sınıfı içerisinde AndAlso metodu generic yapıda olduğundan dolayı istediğimiz tipte bu yapıyı uygulayabiliriz.
harika emeğinize sağlık 👍👍😊