使用通用过滤为字段类型构建Dynamic Where子句

This questions stems from another closed one I posted Here

我有以下电话

        var query = _context.Listings.AsQueryable();
        query = query.WhereEqualIfSpecified(x => x.HasBalcony, true);
        query = query.ApplyRangeFilter(x => x.BedroomsAvailable, 1, 9);
        query = query.ApplyRangeFilter(x => x.Baths, 1.0, 2.5);
        query = query.ApplyRangeFilter(x => x.Price, 1000.00, 2000.00);
        var listings = query.ToList();

I would like to make WhereEqualIfSpecified generic so its not only for bools but once I change the method to following

    public static IQueryable<T> WhereEqualIfSpecified<T>(this IQueryable<T> query, Expression<Func<T, T>> fieldExpression, T filterValue)
    {
        return filterValue is null
            ? query
            : query.Where(fieldExpression.Compose(value => value.Equals(filterValue)));
    }

The call query = query.WhereEqualIfSpecified(x => x.HasBalcony, true); results in compiler error

方法的类型参数   'ExtensionMethods.WhereEqualIfSpecified(IQueryable,   无法从用法中推断出Expression>,T)'。尝试   明确指定类型参数
public partial class Listing
{

    public decimal? Price { get; set; }
    public int? BedroomsAvailable { get; set; }
    public double? Baths { get; set; }

    public bool? HasBalcony { get; set; }
    public bool? HasElevator { get; set; }

}
public static class ExtensionMethods
{

    public static IQueryable<T> WhereEqualIfSpecified<T>(this IQueryable<T> query, Expression<Func<T, bool?>> fieldExpression, bool? filterValue)
    {
        return filterValue is null
            ? query
            : query.Where(fieldExpression.Compose(value => value.Equals(filterValue)));
    }



    public static IQueryable<T> ApplyRangeFilter<T>(this IQueryable<T> query, Expression<Func<T, int?>> filter, int? minValue, int? maxValue)
    {
        if (minValue is null && maxValue is null) return query;

        if (maxValue != null && minValue != null)
        {
            return minValue == maxValue?
                 query.Where(filter.Compose(value => value.Equals(minValue))):
             query.Where(filter.Compose(value => value >= minValue && value <= maxValue));

        }

        return query.Where(maxValue != null ? filter.Compose(value => value.Equals(maxValue)) : filter.Compose(value => value.Equals(minValue)));


    }


    //copied from https://stackoverflow.com/questions/37602729/convert-linq-expression-obj-obj-prop-into-parent-parent-obj-prop/37602870#37602870
    public static Expression<Func<T, TResult>> Compose<T, TIntermediate, TResult>(
        this Expression<Func<T, TIntermediate>> first,
        Expression<Func<TIntermediate, TResult>> second)
    {
        return Expression.Lambda<Func<T, TResult>>(
            second.Body.Replace(second.Parameters[0], first.Body),
            first.Parameters[0]);
    }

    public class ReplaceVisitor : ExpressionVisitor
    {
        private readonly Expression from, to;
        public ReplaceVisitor(Expression from, Expression to)
        {
            this.from = from;
            this.to = to;
        }

        public override Expression Visit(Expression ex)
        {
            return ex == @from ? to : base.Visit(ex);
        }
    }

    public static Expression Replace(this Expression ex,
        Expression from,
        Expression to)
    {
        return new ReplaceVisitor(from, to).Visit(ex);
    }

}

In short, I would like both WhereEqualIfSpecified and ApplyRangeFilter to be generic so it can take any type in instead of using overload functions

评论