It should be something like:
public static Expression<Func<T, bool>> BuildStringEqualLambda<T>(params Tuple<string, string>[] propertyNameValues)
{
if (propertyNameValues == null || propertyNameValues.Length == 0)
{
throw new ArgumentException(nameof(propertyNameValues));
}
ParameterExpression parameterExp = Expression.Parameter(typeof(T), "type");
Expression body = null;
foreach (var propertyNameValue in propertyNameValues)
{
Expression propertyExp = parameterExp;
foreach (var property in propertyNameValue.Item1.Split('.'))
{
propertyExp = Expression.PropertyOrField(propertyExp, property);
}
Expression right = Expression.Constant(propertyNameValue.Item2);
Expression eq = Expression.Equal(propertyExp, right);
body = body == null ? eq : Expression.OrElse(body, eq);
}
return Expression.Lambda<Func<T, bool>>(body, new ParameterExpression[] { parameterExp });
}
You can probably use some funny LINQ with Aggregate
to reduce the number of lines, but it would be undebuggable.
In the end you use the Expression.OrElse
(not the Expression.Or
that is |
!) and you handle the first element case.
Use it like:
var exp = BuildStringEqualLambda(
Tuple.Create("prop1", "value1"),
Tuple.Create("prop2", "value2"),
Tuple.Create("prop3", "value3")
);
Using some LINQ and Aggregate
(for those who can't live without LINQing everything) (note that while I wouldn't ever use the LINQed version of the code... It is quite unreadable... Enumerable.Aggregate
is "terrible" ):
public static Expression<Func<T, bool>> BuildStringEqualLambda<T>(params Tuple<string, string>[] propertyNameValues)
{
if (propertyNameValues == null || propertyNameValues.Length == 0)
{
throw new ArgumentException(nameof(propertyNameValues));
}
ParameterExpression parameterExp = Expression.Parameter(typeof(T), "type");
Expression body = propertyNameValues
.Select(x => BuildEqualityExpression<T>(parameterExp, x.Item1, x.Item2))
.Aggregate((acc, x) => Expression.OrElse(acc, x));
return Expression.Lambda<Func<T, bool>>(body, new ParameterExpression[] { parameterExp });
}
private static Expression BuildEqualityExpression<T>(ParameterExpression parameterExp, string propertyName, string propertyValue)
{
Expression propertyExp = propertyName
.Split('.')
.Aggregate((Expression)parameterExp, (acc, x) => Expression.PropertyOrField(acc, x));
Expression right = Expression.Constant(propertyValue);
Expression eq = Expression.Equal(propertyExp, right);
return eq;
}