I have a list of field names. I am trying to build a predicate to look in the fields to see if they contain the search term. I have gone done the path listed in this original question but do not understand how to do a Contains instead of a NotEqual.
string searchTerm = "Fred";
foreach (var field in FieldNames)
{
myPredicate= myPredicate.And(m => m.*field*.Contains(searchTerm));
}
My code so far:
public static Expression<Func<T, bool>> MultiColumnSearchExpression<T>(string fieldName,string searchValue)
{
var parameter = Expression.Parameter(typeof(T), "m");
var fieldAccess = Expression.PropertyOrField(parameter, fieldName);
//this next line should do a Contains rather then NotEqual but how?
var body = Expression.NotEqual(fieldAccess, nullValue);
var expr = Expression.Lambda<Func<T, bool>>(body, parameter);
return expr;
}
So you want to call String.Contains
method.
It is a String
class instance method with the following signature
public bool Contains(string value)
which can be mapped to the following Expression.Call
overload:
public static MethodCallExpression Call(
Expression instance,
string methodName,
Type[] typeArguments,
params Expression[] arguments
)
And here is how:
public static Expression<Func<T, bool>> ContainsPredicate<T>(string memberName, string searchValue)
{
var parameter = Expression.Parameter(typeof(T), "m");
var member = Expression.PropertyOrField(parameter, memberName);
var body = Expression.Call(
member,
"Contains",
Type.EmptyTypes, // no generic type arguments
Expression.Constant(searchValue)
);
return Expression.Lambda<Func<T, bool>>(body, parameter);
}
Expression.NotEqual
is the binary operator !=
. Since your Contains
call is not a binary operator, there is no direct replacement for this.
Instead, what you need to do is a method call of Contains
. So you first need to get the MethodInfo
object for the string.Contains
function.
It should look like this:
var method = typeof(string).GetMethod("Contains");
var body = Expression.Call(fieldAccess, method, Expression.Constant(searchValue));