使用包含值类型和字符串的表达式树创建动态Linq查询?

时间:2018-01-15 22:14:09

标签: c# linq linq-to-entities predicatebuilder

我正在尝试创建一个动态搜索表达式树,它采用表列列表和搜索词数组并返回表达式。下面的代码适用于非值类型,但我无法弄清楚如何使它与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时,我当前得到并出错。错误是

  

没有方法&#39;等于&#39; on type&#39; System.Nullable`1 [System.Int32]&#39;与提供的参数兼容。

1 个答案:

答案 0 :(得分:-1)

使用LINQPad并分析lambda,编译器似乎将Int32常量转换为Object并调用Object Equals(object)版本:

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