我正在开发一个应用动态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
所以我的问题是:有什么方法可以实现通用方法?
答案 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
。