I use this piece of code (found on stackoverflow) to generate a predicate
static class BuilderPredicate
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
I have this object :
public class Person : IPerson
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IPerson
{
int Id { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
}
To use to, I do this :
private void CreationPredicate(string fieldname, string stringToSearch)
{
var predicate = BuilderPredicate.True<Person>();
switch (fieldname)
{
case "FirstName":
predicate = predicate.And(e => e.FirstName.StartsWith(stringToSearch));
break;
case "LastName":
predicate = predicate.And(e => e.LastName.StartsWith(stringToSearch));
break;
}
}
I'd like avoid, the switch and replace e => e.FirstName.StartWith
by (if possible)
e => e.fieldname.StartWith
How can I do this ?
Thanks,
If you are using strings, you need to build the expression the hard way:
var param = Expression.Parameter(typeof (Foo));
var pred = Expression.Lambda<Func<Foo, bool>>(
Expression.Call(
Expression.PropertyOrField(param, fieldName),
"StartsWith",null,
Expression.Constant(stringToSearch)), param);
On 4.0, I'd also have used an ExpressionVisitor
to rewrite the body for the "and", rather than an Invoke
; Invoke
is not supported on EF etc.