I have a Linq Expression, which may be altered depending on certain conditions. An example of what I would like to do (left blank the bit I am not sure about):
I think you want to combine filters this way:
var myFilters = new List>>();
myFilters.Add(c => c.Name.StartsWith("B"));
myFilters.Add(c => c.Orders.Count() == 3);
if (stranded)
{
myFilters.Add(c => c.Friends.Any(f => f.Cars.Any())); //friend has car
}
Expression> filter = myFilters.AndTheseFiltersTogether();
IEnumerable thoseCustomers = Data.Get(filter);
This code will allow you to combine your filters.
public static Expression> OrTheseFiltersTogether(params Expression>[] filters)
{
return filters.OrTheseFiltersTogether();
}
public static Expression> OrTheseFiltersTogether(this IEnumerable>> filters)
{
if (!filters.Any())
{
Expression> alwaysTrue = x => true;
return alwaysTrue;
}
Expression> firstFilter = filters.First();
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> result = Expression.Lambda>(body, param);
return result;
}
public static Expression> AndTheseFiltersTogether(params Expression>[] filters)
{
return filters.AndTheseFiltersTogether();
}
public static Expression> AndTheseFiltersTogether(this IEnumerable>> filters)
{
if (!filters.Any())
{
Expression> alwaysTrue = x => true;
return alwaysTrue;
}
Expression> firstFilter = filters.First();
var body = firstFilter.Body;
var param = firstFilter.Parameters.ToArray();
foreach (var nextFilter in filters.Skip(1))
{
var nextBody = Expression.Invoke(nextFilter, param);
body = Expression.AndAlso(body, nextBody);
}
Expression> result = Expression.Lambda>(body, param);
return result;
}