@lucky4

Как написать поиск-фильтрацию по всем типам?

Делаю фильтрацию по полям. Изначально был вариант, поиск только по string, и что бы поиск был Equal. Теперь хотел, усложнить задачу, что бы была фильтрация по Contains, и заодно что бы можно было искать по всем типам, типу int / decimal / double ...

private static Expression<Func<T, bool>> GetExpression<T, R>(string propertyName, R propertyValue)
        {
            var parametr = Expression.Parameter(typeof(T));
            var property = Expression.Property(parametr, propertyName);
            var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(R) });

            var objectContains = Expression.Constant(propertyValue, typeof(R));
            var objectEquals   = Expression.Equal(property, Expression.Constant(propertyValue));

            var constrantMethod = Expression.Call(property, containsMethod, objectContains);

            return Expression.Lambda<Func<T, bool>>(constrantMethod, parametr)
                .Or(Expression.Lambda<Func<T, bool>>(objectEquals, parametr));
        }

        public static IQueryable<T> ApplyFiltering<T, R>(this IQueryable<T> source, string propertyLabel, R propertyValue)
        {
            var propertyNames = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
                              .Where(property => property.PropertyType == typeof(R) && property.Name == propertyLabel)
                              .Select(x => x.Name);

            var predicate = PredicateBuilder.New<T>();

            foreach (var name in propertyNames)
            {
                predicate = predicate.Or(GetExpression<T, R>(name, propertyValue));
            }

            return source.Where(predicate);
        }
  • Вопрос задан
  • 62 просмотра
Пригласить эксперта
Ответы на вопрос 2
@cicatrix
было бы большой ошибкой думать
Как-то так, наверное:
public static IQueryable<T> ApplyFiltering<T>(
    this IQueryable<T> source, 
    string propertyName, 
    string filter)
{
        filter = filter.ToLower(); // выключить зависимость от регистра
        return source
            .Where(item => 
            item.GetType()
            .GetProperty(propertyName)
            .GetValue(item, null)
            .ToString().ToLower().Contains(filter));
} // ApplyFiltering
Ответ написан
twobomb
@twobomb
Типа такого, fieldsSearch это имена полей по которым будет идти поиск, searchValue это искомое значение
public IQueryable<T> applyFilter<T>(IQueryable<T> source, List<string> fieldsSearch, object searchValue){
            var propertyNames = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
                              .Where(p => fieldsSearch.Contains(p.Name));
            return source.Where(new Func<T, bool>(s =>
            {
                foreach (var propertyName in propertyNames){
                    var v = propertyName.GetValue(s, null);
                    if (v != null && v.ToString().Contains(searchValue.ToString()))
                        return true;
                }
                return false;
            })).AsQueryable();
        }
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы