比较linq和sql

时间:2019-01-16 04:11:44

标签: c# linq generics

我正在开发一个应用动态linq查询的c#dll库。 我定义了通用接口和通用日期类型,如下所示:

public interface IRangeValue<T> where T : struct
{
    Nullable<T> GetHigh();
    Nullable<T> GetLow();
    void SetHigh(Nullable<T> val);
    void SetLow(Nullable<T> val);

}

public class RangeT<T> : IRangeValue<T>
    where T :struct
{
    public Nullable<T> High { get; set; }
    public Nullable<T> Low { get; set; }
    public Nullable<T> GetHigh() { return High; }
    public Nullable<T> GetLow() { return Low; }
    public void SetHigh(Nullable<T> val) { High = val; }
    public void SetLow(Nullable<T> val) { Low = val; }
}

然后我在代码中使用通用日期类型,如下所示:

    public static Expression<Func<T, bool>> RangeCompare<T>(Expression<Func<T, DateTime>> selector, RangeT<DateTime> patten)
            {
                Expression<Func<T, bool>> predicate = PredicateBuilder.True<T>();
                if (patten.GetHigh().HasValue)
                {
                    predicate = predicate.And<T>(s => selector.Compile()(s) <= patten.GetHigh().Value);
                }
                if (patten.GetLow().HasValue)
                {
                    predicate = predicate.And<T>(s => selector.Compile()(s).Equals(patten.GetLow().Value));
                }
                return predicate;
            }
  public static Expression<Func<T, bool>> RangeCompare<T>(Expression<Func<T, int>> selector, RangeT<int> patten)
            {
                Expression<Func<T, bool>> predicate = PredicateBuilder.True<T>();
                if (patten.GetHigh().HasValue)
                {
                    predicate = predicate.And<T>(s => selector.Compile()(s) <= patten.GetHigh().Value);
                }
                if (patten.GetLow().HasValue)
                {
                    predicate = predicate.And<T>(s => selector.Compile()(s) >= patten.GetLow().Value);
                }
                return predicate;
            }

实际上,如果忽略输入类型,则这两种方法的主体相同。因此,我尝试编写一种新的通用方法来替换这两种方法。如下所示的新方法:

        public static Expression<Func<T, bool>> RangeCompare<T>(Expression<Func<T, K>> selector, IRangeValue<K> patten)
    {
        Expression<Func<T, bool>> predicate = PredicateBuilder.True<T>();
        if (patten.GetHigh().HasValue)
        {
            predicate = predicate.And<T>(s => selector.Compile()(s) <= patten.GetHigh().Value);
        }
        if (patten.GetLow().HasValue)
        {
            predicate = predicate.And<T>(s => selector.Compile()(s) >= patten.GetLow().Value);
        }
        return predicate;
    }

我用IRangeValue替换了参数RangeT(RangeT)。 现在,编译器告诉我类似“ <=”,“> =”之类的运算符错误,因为无法推断出通用类型K

所以我的问题是:有什么方法可以实现通用方法?

1 个答案:

答案 0 :(得分:0)

如果您正在使用LINQ to Objects,则处理通用比较的标准方法是使用Comparer类。

public static Expression<Func<T, bool>> RangeCompare<T, K>(Func<T, K> selector, IRangeValue<K> patten) where K : struct {
    var cmp = Comparer<K>.Default;

    Expression<Func<T, bool>> predicate = PredicateBuilder.True<T>();
    if (patten.GetHigh().HasValue)
        predicate = predicate.And<T>(s => cmp.Compare(selector(s), patten.GetHigh().Value) <= 0);
    if (patten.GetLow().HasValue)
        predicate = predicate.And<T>(s => cmp.Compare(selector(s), patten.GetLow().Value) >= 0);

    return predicate;
}

注意:我将方法更改为采用Func,因此您无需调用Compile