奇怪的是你不能修改你的MyFilterAsync,你确定吗?因为排序、跳过和获取的要求需要更多的参数,而不仅仅是filter。因此,最好为 MyFilterAsync 编写更多重载以接受更多参数并编写与其他用户建议的代码类似的代码。
但是在这里,我试图让您的MyFilterAsync 保持不变,但您仍然可以加入订购、跳过和获取的逻辑。这一点都不神奇,但您仍然需要编写其他代码:您自己的扩展方法来替换默认的Where。这取决于编译器如何选择扩展方法重载。对于实体类型,默认具有最通用的 TEntity 类型。您只需在类型上使您的扩展方法重载更具体,例如:您的示例中的 Languages 类型。它可以是您的基本实体类型。当它不太通用(更具体)时,编译器将使用您的扩展重载而不是默认重载。
您可以通过以下方式使其发挥作用:
//put this in the same namespace with the default
//extension methods defined in System.Linq.Queryable
public static class YaQueryableExtensions
{
static readonly AsyncLocal<int> _skip = new AsyncLocal<int>();
static readonly AsyncLocal<int> _take = new AsyncLocal<int>();
static class ExpressionBuffers<TEntity>
{
public static readonly AsyncLocal<Expression<Func<TEntity, object>>> OrderBy =
new AsyncLocal<Expression<Func<TEntity, object>>>();
}
//here is your own extension method for Where
//targeting the specific type of Languages
//which can be any base entity type (if you want it to apply on a broader scope)
public static IQueryable<Languages> Where(this IQueryable<Languages> source,
Expression<Func<Languages, bool>> filter)
{
return source.WhereWithExpressionBuffers(filter);
}
//the generic helper method which can be used on a specific closed type
//of T (this method can be made private)
public static IQueryable<T> WhereWithExpressionBuffers<T>(this IQueryable<T> source,
Expression<Func<T, bool>> filter)
{
source = Queryable.Where(source, filter);
//check for order-by (which should be chained first if any)
var orderBy = ExpressionBuffers<T>.OrderBy.Value;
if(orderBy != null)
{
source = source.OrderBy(orderBy);
ExpressionBuffers<T>.OrderBy.Value = null;
}
//check for skip
var skip = _skip.Value;
if (skip > 0)
{
source = source.Skip(_skip.Value);
_skip.Value = 0;
}
//check for take
var take = _take.Value;
if (take > 0)
{
source = source.Take(take);
_take.Value = 0;
}
return source;
}
public static Expression<Func<T, bool>> Skip<T>(this Expression<Func<T, bool>> filter, int skip)
{
_skip.Value = skip;
return filter;
}
public static Expression<Func<T, bool>> Take<T>(this Expression<Func<T, bool>> filter, int take)
{
_take.Value = take;
return filter;
}
public static Expression<Func<TEntity, bool>> OrderBy<TEntity>(this Expression<Func<TEntity, bool>> filter,
Expression<Func<TEntity,object>> orderBy)
{
ExpressionBuffers<TEntity>.OrderBy.Value = orderBy;
return filter;
}
}
现在是你如何使用它:
var result = await MyFilterAsync(filter.OrderBy(e => e.Name).Skip(skip).Take(pageSize));
OrderBy、Skip 和 Take 被链接在 filter 上(使用我们的扩展方法),以便它们可以被缓冲以供以后在我们自己的 Where 扩展方法中使用,我们可以在其中读取缓冲表达式以按照我们想要的方式正确构建Where)。
注意:您应该将您的扩展类与Queryable(即System.Linq)放在同一个命名空间中,以便您的扩展方法可以自动可用(当然会使用默认扩展方法)。