Создание динамического запроса Linq с использованием дерева выражений как с типами значений, так и со строками?

Я пытаюсь создать динамическое дерево выражений поиска, которое принимает список столбцов таблицы и массив условий поиска и возвращает выражение. Приведенный ниже код отлично работает с незначащими типами, но я не могу понять, как заставить его работать со свойствами ValueType. то есть строки работают, а числа нет.

    public static Expression<Func<T, bool>> CreateDynamicSearch<T>(List<string> searchableColumns, string[] searchTerms)
    {
        var predicate = PredicateBuilder.New<T>(true);
        try {
            foreach (var term in searchTerms) {
                var colPredicate = PredicateBuilder.New<T>(true);
                foreach (var columnName in searchableColumns) {
                    var columnFilter = PredicateBuilder.New<T>(false);
                    var param = Expression.Parameter(typeof(T), "a");
                    MemberExpression prop = Expression.Property(param, columnName);
                    var propInfo = (PropertyInfo)prop.Member;
                    MethodCallExpression call;
                    if (propInfo.PropertyType.IsValueType) {
                        if (int.TryParse(term, out int num)) {
                            call = Expression.Call(prop, "Equals", new Type[0],Expression.Constant(num)); 
                            columnFilter = columnFilter.And(Expression.Lambda<Func<T, bool>>(call, param));
                            colPredicate = colPredicate.Or(columnFilter);
                        }
                    }
                    else {
                        call = Expression.Call(prop, "Contains", new Type[0], Expression.Constant(term));
                        columnFilter = columnFilter.And(Expression.Lambda<Func<T, bool>>(call, param));
                        colPredicate = colPredicate.Or(columnFilter);
                    }
                }
                //AND the term predicate with the previous predicate
                predicate = predicate.And(colPredicate);
            }
        }
        catch (Exception ex) {
            throw;
        }
        return predicate;
    }

Я просто копаюсь в деревьях выражений, поэтому любые предложения будут оценены.

Используя этот код, я в настоящее время получаю и получаю ошибку, когда добираюсь до ValueType. Ошибка

Никакой метод «Equals» для типа «System.Nullable`1[System.Int32]» не совместим с предоставленными аргументами.


person John S    schedule 15.01.2018    source источник
comment
Что происходит, когда вы пытаетесь обработать Int?   -  person NetMage    schedule 16.01.2018
comment
Я получаю сообщение об ошибке, которое я добавил выше.   -  person John S    schedule 17.01.2018
comment
Хорошо, кажется, что это как-то связано с тем фактом, что поле БД является целым числом, допускающим значение NULL (не мой вызов). Если бы DB был истинным int, Equals работал бы просто отлично.   -  person John S    schedule 17.01.2018
comment
Вы попробовали мое предложение изменить с помощью Convert?   -  person NetMage    schedule 18.01.2018
comment
Преобразование в этом случае не сработало, потому что тип переменной num был целым числом, допускающим значение NULL.   -  person John S    schedule 18.01.2018
comment
Когда я использовал LINQPad и создал лямбду с нулевым целым, это был код, сгенерированный компилятором.   -  person NetMage    schedule 18.01.2018


Ответы (1)


Используя LINQPad и анализируя лямбду, кажется, что компилятор преобразует константу Int32 в Object и вызывает версию Object Equals(object):

Expression.Call(prop, "Equals", new Type[0], Expression.Convert(Expression.Constant(num), typeof(Object))); 
person NetMage    schedule 15.01.2018