我试图编写一个通用扩展方法来订购一个IQueryable数据库集合。 (还有更多内容,但这就是我所喜欢的部分。)
我想提供:
- 数据库类(例如客户,雇主)
- 列的LINQ表达式
- 列的类型(int,string等)
醇>
我从一个应该包含信息的类开始,但是我遇到了如何定义和使用表达式的问题。
对于用法,我正在考虑这样的事情,但不确定在哪里为每列提供类型
var sortedList = queryable.MyCustomSortMethod<User>( item => new List<SortItem>
{ item.Column_Name, "ASC" }, //string
{ item.Column_BirthYear "DESC" }, //int
{ item.Column_BirthDate, "ASC" } //date
}
然后我有一个类来指定选择器及其方向
public class SortItem<TEntity>
{
public Expression<Func<T> SortFieldSelector<T> { get; set; }
public SortDirectionType SortDirectionType { get; set; }
//but how to provide column type
}
然后扩展方法就像这样
public static IQueryable<TEntity> MyCustomSortMethod(
this IQueryable<TEntity> queryable,
List<SortItem<TEntity> selectors)
{
foreach (var selector in selectors) {
if(selector.Direction == "asc")
queryable = queryable.OrderBy(selector.SortFieldSelector);
else
queryable = queryable.OrderByDescending(selector.SortFieldSelector);
}
//I need to specify the type of the OrderBy column somehow
// otherwise compiler errors with "arguments cannot be inferred..."
return queryable;
}
我正在探索的兔子洞变得非常丑陋,我确信有一种简单的方法可以做到。
我需要使用扩展方法的事实是一个坚定的要求,但如果它简化了解决方案,其余部分仍然是灵活的。
非常感谢任何帮助。
答案 0 :(得分:1)
您可以这样做:
public class SortItem<TEntity>
{
public Expression<Func<TEntity, object>> Selector { get; }
public ListSortDirection Direction { get; }
public SortItem(Expression<Func<TEntity, object>> selector, ListSortDirection direction)
{
Selector = selector;
Direction = direction;
}
}
public static IQueryable<TEntity> MyCustomSortMethod<TEntity>(
this IQueryable<TEntity> queryable,
IEnumerable<SortItem<TEntity>> selectors)
{
foreach (var selector in selectors)
{
IOrderedQueryable<TEntity> ordered = queryable as IOrderedQueryable<TEntity>;
if (ordered == null)
{
if (selector.Direction == ListSortDirection.Ascending)
queryable = queryable.OrderBy(selector.Selector);
else
queryable = queryable.OrderByDescending(selector.Selector);
}
else
{
if (selector.Direction == ListSortDirection.Ascending)
queryable = ordered.ThenBy(selector.Selector);
else
queryable = ordered.ThenByDescending(selector.Selector);
}
}
return queryable;
}
(请注意使用ThenBy
代替OrderedBy
;如果您每次都使用OrderBy
,则只会覆盖之前的订单,而不是完成订单。
免责声明:我没有尝试过,所以我不确定它是否适用于Func<TEntity, object>
。