【问题标题】:Creating an Extension Method using Expressions使用表达式创建扩展方法
【发布时间】:2016-10-02 21:50:46
【问题描述】:

我正在尝试编写一个通用扩展方法来订购 IQueryable 数据库集合。 (还有更多,但这是我坚持的部分。)

我想提供:

  1. 数据库类(例如 Customer、Employer)
  2. 列的 LINQ 表达式
  3. 列的类型(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;

}

我正在探索的兔子洞越来越难看,我相信有一个简单的方法可以做到。

我需要使用扩展方法这一事实是一个坚定的要求,但如果它简化了解决方案,其余的仍然是灵活的。

非常感谢任何帮助。

【问题讨论】:

  • 有什么意义?似乎没有比queryable.OrderBy(item =&gt; item.Column_Name).ThenByDescending(item =&gt; item.Column_BirthYear).ThenBy(item =&gt; item.Column_BirthDate)更容易使用
  • @Thomas - 不幸的是,在这种情况下我不能这样做。如果列表为空(并且基于一些附加参数),扩展方法有一些额外的逻辑。我试图将该逻辑包含在扩展方法中,以避免调用代码中的代码重复。

标签: c# linq lambda extension-methods


【解决方案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&lt;TEntity, object&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多