【问题标题】:Compare two generic type in linq to sql将 linq 中的两个泛型类型与 sql 进行比较
【发布时间】:2019-01-16 04:11:43
【问题描述】:

我正在开发一个应用动态 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;
    }

我将参数 RangeT(RangeT) 替换为 IRangeValue。 现在编译器告诉我像'='这样的运算符错误,因为无法推断出泛型类型K

所以我的问题是:有什么方法可以实现泛型方法吗?

【问题讨论】:

  • 为什么不在接口中定义属性而不是get和set方法?
  • 相信你想用Expression.LessThanOrEqualExpression.GreaterThanOrEqual
  • 你不需要RangeCompare 来拥有K 泛型类型参数吗?如果您仍然要调用Compile(),为什么要将selector 传递为Expression&lt;Func&lt;&gt;&gt; 而不仅仅是Func&lt;&gt;
  • 您是使用 LINQ to SQL 还是 EF,还是全部使用 LINQ to Objects?

标签: c# linq generics


【解决方案1】:

如果您正在使用 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

【讨论】:

    猜你喜欢
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多