概括而不失类型
Generalize without losing type
我需要将这两种方法合并为一个概括它们的方法。我知道 IQueryable 实现 IEnumerable,IOrderedQueryable 实现 IOrderedEnumerable,如果存在第二个方法,第一个方法似乎没用。但是由于某些 Entity Framework 原因,第二个中断了服务器端查询转换 (Linq-to-SQL)
private static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
private static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
这些方法违反了 DRY 规则,非常烦人。
即使代码看起来相同,它们也不能在相同的类型上工作,也不能使用泛型,因为 where 子句只能 AND 组合多个给定值。
所以你所能做的就是把计算逻辑分解出来,但是如果这真的更好的可读性和可维护性真的取决于你的态度。
private static bool TryCalculateRange(int totalCount, int pageLength, int page, out int skip, out int take)
{
skip = 0;
take = 0;
if(pageLength <= 0)
return false;
skip = pageLength * (page - 1);
if(skip >= totalCount)
skip = 0;
take = totalCount - skip;
if(take > pageLength)
take = pageLength;
return true;
}
public static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
int skip;
int take;
return TryCalculateRange(totalRows, reqLength, pageNum, out skip, out take))
? data.Skip(skip).Take(take)
: data;
}
public static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
int skip;
int take;
return TryCalculateRange(totalRows, reqLength, pageNum, out skip, out take))
? data.Skip(skip).Take(take)
: data;
}
}
我需要将这两种方法合并为一个概括它们的方法。我知道 IQueryable 实现 IEnumerable,IOrderedQueryable 实现 IOrderedEnumerable,如果存在第二个方法,第一个方法似乎没用。但是由于某些 Entity Framework 原因,第二个中断了服务器端查询转换 (Linq-to-SQL)
private static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
private static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
if (reqLength == 0)
return data;
else
{
int skipRows = reqLength * (pageNum - 1);
if (skipRows >= totalRows)
skipRows = 0;
int diff = totalRows - skipRows;
return data.Skip(skipRows).Take(diff > reqLength ? reqLength : diff);
}
}
这些方法违反了 DRY 规则,非常烦人。
即使代码看起来相同,它们也不能在相同的类型上工作,也不能使用泛型,因为 where 子句只能 AND 组合多个给定值。
所以你所能做的就是把计算逻辑分解出来,但是如果这真的更好的可读性和可维护性真的取决于你的态度。
private static bool TryCalculateRange(int totalCount, int pageLength, int page, out int skip, out int take)
{
skip = 0;
take = 0;
if(pageLength <= 0)
return false;
skip = pageLength * (page - 1);
if(skip >= totalCount)
skip = 0;
take = totalCount - skip;
if(take > pageLength)
take = pageLength;
return true;
}
public static IQueryable<T> Pag<T>(IOrderedQueryable<T> data, int totalRows, int reqLength, int pageNum)
{
int skip;
int take;
return TryCalculateRange(totalRows, reqLength, pageNum, out skip, out take))
? data.Skip(skip).Take(take)
: data;
}
public static IEnumerable<T> Pag<T>(IOrderedEnumerable<T> data, int totalRows, int reqLength, int pageNum)
{
int skip;
int take;
return TryCalculateRange(totalRows, reqLength, pageNum, out skip, out take))
? data.Skip(skip).Take(take)
: data;
}
}