This is exactly where dynamic expression building is useful:
public string[] GetPeopleAutoComplete( string filter, int maxResults, string searchType, string searchOption) { IQueryable<Person> query = _context.People; var property = typeof(Person).GetProperty(searchType); var method = typeof(string).GetMethod(searchOption, new[] { typeof(string) }); query = query.Where(WhereExpression(property, method, filter)); var resultQuery = query.Select(SelectExpression(property)); if (searchType == "Firstname" || searchType == "Lastname") resultQuery = resultQuery.Distinct(); return resultQuery.Take(maxResults).ToArray(); } Expression<Func<Person, bool>> WhereExpression( PropertyInfo property, MethodInfo method, string filter) { var param = Expression.Parameter(typeof(Person), "o"); var propExpr = Expression.Property(param, property); var methodExpr = Expression.Call(propExpr, method, Expression.Constant(filter)); return Expression.Lambda<Func<Person, bool>>(methodExpr, param); } Expression<Func<Person, string>> SelectExpression(PropertyInfo property) { var param = Expression.Parameter(typeof(Person), "o"); var propExpr = Expression.Property(param, property); return Expression.Lambda<Func<Person, string>>(propExpr, param); }
This does not solve your default case, but it should be relatively easy to add. Also, using this reflection can be slow, so you can cache the results of GetProperty() and GetMethod() .
Another thing to note is that the part that chooses whether to use Distinct() still depends on the property names, but maybe you have a better condition for this (or you can use attributes for the properties )
And the two helper methods do not need to know anything about Person , so it would be trivial to make them generalized.
source share