扩展Marc Gravell的动态Linq OrderBy

Tom*_*len 7 c# linq linq-to-objects dynamic sql-order-by

我发现Marc Gravell的动态秩序很棒:

IEnumerable <T>上的动态LINQ OrderBy

我把它放在课堂上了LinqHelper.在这个类中我还创建了两个新类,因此在我的代码中我可以这样做:

var q = db.tblJobHeaders;

LinqHelper.OrderByCollection OBys = new LinqHelper.OrderByCollection();
OBys.AddOrderBy("some field", true);
OBys.AddOrderBy("anotherfield", false);
OBys.ExecuteOrderBys(q);
Run Code Online (Sandbox Code Playgroud)

实现这一目标的课程是:

/// <summary>
/// A collection of order bys
/// </summary>
public class OrderByCollection
{
    private ArrayList Orderings = new ArrayList();

    public OrderByCollection(){ }

    /// <summary>
    /// Add an order by to this collection
    /// </summary>
    public void AddOrderBy(string Field, bool Descending)
    {
        OrderByObj NewObj = new OrderByObj(Descending, Field);
        this.Orderings.Add(NewObj);
    }

    /// <summary>
    /// Executes the order bys
    /// </summary>
    public IOrderedQueryable<T> ExecuteOrderBys<T>(this IOrderedQueryable<T> source)
    {
        int ExecutionIndex = 0;
        foreach (OrderByObj O in this.Orderings)
        {
            if (ExecutionIndex == 0)
            {
                if (O.Descending)
                    source = LinqHelper.OrderByDescending(source, O.Field);
                else
                    source = LinqHelper.OrderBy(source, O.Field);
            }
            else
            {
                if (O.Descending)
                    source = LinqHelper.ThenByDescending(source, O.Field);
                else
                    source = LinqHelper.ThenBy(source, O.Field);
            }
            ExecutionIndex++;
        }
        return (IOrderedQueryable<T>)source;
    }
}

/// <summary>
/// An order by object
/// </summary>
private class OrderByObj
{
    public bool Descending { get; set; }
    public string Field { get; set; }

    public OrderByObj(bool IsDescending, string DatabaseField)
    {
        this.Descending = IsDescending;
        this.Field = DatabaseField;
    }
}
Run Code Online (Sandbox Code Playgroud)

无论我如何将Linq vars传递给函数(让我有点困惑).我目前收到错误:

OBys.ExecuteOrderBys(q);
Run Code Online (Sandbox Code Playgroud)

这给出了错误:

无法从用法推断出方法'LinqHelper.OrderByCollection.ExecuteOrderBys(System.Linq.IOrderedQueryable)'的类型参数.尝试显式指定类型参数.

如果有人能提供帮助,我对此感到有点困惑,我var q是否正确地将其传入,然后正确地将其归还?

R. *_*des 4

q我敢打赌isIQueryable<T>和 not的类型IOrderedQueryable<T>。只需更改签名就可以了,因为您以OrderBy.

然后你将需要一个IOrderedQueryable<T>for ThenBys。您可以直接投射它,因为您确信您有一个IOrderedQueryable<T>来自上一次调用的OrderByor ThenBy

如果您不喜欢演员阵容的想法,则需要进行一些更改:

public IOrderedQueryable<T> ExecuteOrderBys<T>(this IQueryable<T> source)
{
    if(!this.Orderings.Any())
        throw new InvalidOperationException("You need to add orderings");
    IOrderedQueryable<T> ordered;
    if (this.Orderings[0].Descending)
        ordered = LinqHelper.OrderByDescending(source, this.Orderings[0].Field);
    else
        ordered = LinqHelper.OrderBy(source, this.Orderings[0].Field);
    foreach(var ordering in this.Orderings.Skip(1))
    {
        if (ordering.Descending)
            ordered = LinqHelper.ThenByDescending(source, ordering.Field);
        else
            ordered = LinqHelper.ThenBy(source, ordering.Field);
    }
    return ordered;
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您不添加任何顺序,您的代码将会严重失败,因为IOrderedQueryable<T>最后会进行强制转换。您可以将返回类型更改为IQueryable<T>(这会失去稍后“附加”更多 OrderBy 的能力),或者如果没有订单则抛出异常,就像我所做的那样。