当前位置 : 主页 > 网络推广 > seo >

linq – 如何从IQueryable对象中检索订购信息?

来源:互联网 收集:自由互联 发布时间:2021-06-16
比方说,我有一个IQueryable的例子.我怎样才能找到订购的参数? 以下是OrderBy()方法的外观(作为参考): public static IOrderedQueryableT OrderByT, TKey( this IQueryableT source, ExpressionFuncT, TKey keySelector
比方说,我有一个IQueryable的例子.我怎样才能找到订购的参数?

以下是OrderBy()方法的外观(作为参考):

public static IOrderedQueryable<T> OrderBy<T, TKey>(
    this IQueryable<T> source, Expression<Func<T, TKey>> keySelector)
{
    return (IOrderedQueryable<T>)source.Provider.CreateQuery<T>(
        Expression.Call(null,
            ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(
                    new Type[] { typeof(T), typeof(TKey) }
            ),
            new Expression[] { source.Expression, Expression.Quote(keySelector) }
        )
    );
}

马特沃伦的暗示:

All queryables (even IOrderedQueryable’s) have expression trees underlying them that encode the activity they represent. You should find using the IQueryable.Expression property a method-call expression node representing a call to the Queryable.OrderBy method with the actual arguments listed. You can decode from the keySelector argument the expression used for ordering. Take a look at the IOrderedQueryable object instance in the debugger to see what I mean.

这不是很好,但它似乎做了这个工作:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Windows.Forms;

public class Test
{
    public int A;
    public string B { get; set; }
    public DateTime C { get; set; }
    public float D;
}
public class QueryOrderItem
{
    public QueryOrderItem(Expression expression, bool ascending)
    {
        this.Expression = expression;
        this.Ascending = ascending;
    }
    public Expression Expression { get; private set; }
    public bool Ascending { get; private set; }
    public override string ToString()
    {
        return (Ascending ? "asc: " : "desc: ") + Expression;
    } 
}
static class Program
{

    public static List<QueryOrderItem> GetQueryOrder(Expression expression)
    {
        var members = new List<QueryOrderItem>(); // queue for easy FILO
        GetQueryOrder(expression, members, 0);
        return members;
    }
    static void GetQueryOrder(Expression expr, IList<QueryOrderItem> members, int insertPoint)
    {
        if (expr == null) return;
        switch (expr.NodeType)
        {
            case ExpressionType.Call:
                var mce = (MethodCallExpression)expr;
                if (mce.Arguments.Count > 1)
                {   // OrderBy etc is expressed in arg1
                    switch (mce.Method.Name)
                    { // note OrderBy[Descending] shifts the insertPoint, but ThenBy[Descending] doesn't
                        case "OrderBy": // could possibly check MemberInfo
                            members.Insert(insertPoint, new QueryOrderItem(mce.Arguments[1], true));
                            insertPoint = members.Count; // swaps order to enforce stable sort
                            break;
                        case "OrderByDescending":
                            members.Insert(insertPoint, new QueryOrderItem(mce.Arguments[1], false));
                            insertPoint = members.Count;
                            break;
                        case "ThenBy":
                            members.Insert(insertPoint, new QueryOrderItem(mce.Arguments[1], true));
                            break;
                        case "ThenByDescending":
                            members.Insert(insertPoint, new QueryOrderItem(mce.Arguments[1], false));
                            break;
                    }
                }
                if (mce.Arguments.Count > 0)
                {   // chained on arg0
                    GetQueryOrder(mce.Arguments[0], members, insertPoint);
                }
                break;
        }
    }
    static void Main()
    {
        var data = new[] {
            new Test { A = 1, B = "abc", C = DateTime.Now, D = 12.3F},
            new Test { A = 2, B = "abc", C = DateTime.Today, D = 12.3F},
            new Test { A = 1, B = "def", C = DateTime.Today, D = 10.1F}
        }.AsQueryable();
        var ordered = (from item in data
                       orderby item.D descending
                       orderby item.C
                       orderby item.A descending, item.B
                       select item).Take(20);
        // note: under the "stable sort" rules, this should actually be sorted
        // as {-A, B, C, -D}, since the last order by {-A,B} preserves (in the case of
        // a match) the preceding sort {C}, which in turn preserves (for matches) {D}

        var members = GetQueryOrder(ordered.Expression);
        foreach (var item in members)
        {
            Console.WriteLine(item.ToString());
        }

        // used to investigate the tree
        TypeDescriptor.AddAttributes(typeof(Expression), new[] {
            new TypeConverterAttribute(typeof(ExpandableObjectConverter)) });
        Application.Run(new Form
        {
            Controls = { 
            new PropertyGrid { Dock = DockStyle.Fill, SelectedObject = ordered.Expression }
        }
        });

    }
}
网友评论