Search code examples
c#.netlinq-to-entitiesdynamic-dataexpression

How do I filter for a custom column?


I am trying to do something like the following, except I would like to filter based on a parameter that is passed into the function. The following code works perfectly.

public void Test()
{
    var clist = GetFilteredList("Scott");
}

public List<Customer> GetFilteredList1(string filterValue)
{
    IQueryable<Customer> returnQuery = GetAll();

    returnQuery = returnQuery.Where(x => x.FirstName.Contains(filterValue));

    return returnQuery.ToList();
}

What I attempted to do was something like this...

public void Test()
{
    var clist = GetFilteredList2("FirstName", "Scott");
}

public List<Customer> GetFilteredList2(string fieldName, string filterValue)
{
    IQueryable<Customer> returnQuery = GetAll();
    returnQuery = returnQuery
        .Where(x => x.GetType().GetProperty(fieldName).GetValue(x).ToString()
            .Contains(filterValue));                          

    return returnQuery.ToList();
}

I know this isn't quite right, and I suspect I need to somehow use the Expression class to build a custom expression, but I'm not quite sure how. The Expression class doesn't have a "Contains" or a "Like" function in it, so how would I build a custom expression for this?


Solution

  • I was able to solve this by utilizing the System.Linq.Expressions library. Something like this:

    public static Expression<Func<T, bool>> LikeLambdaString<T>(string propertyName, string value)
    {
        var linqParam = Expression.Parameter(typeof(T), propertyName);
        var linqProp = GetProperty<T>(linqParam, propertyName);
    
        var containsFunc = Expression.Call(linqProp,
            typeof(string).GetMethod("Contains"),
            new Expression[] { Expression.Constant(value) });
    
        return Expression.Lambda<Func<T, bool>>(containsFunc,
            new ParameterExpression[] { linqParam });
    }