예제 #1
0
    private static IQueryable <T> ApplyOrderBy <T>(IQueryable <T> collection, OrderByInfo orderByInfo)
    {
        Type type = typeof(T);

        ParameterExpression arg  = Expression.Parameter(type, "x");
        Expression          expr = arg;

        string prop = orderByInfo.PropertyName;

        // use reflection (not ComponentModel) to mirror LINQ
        PropertyInfo pi = OrmHelper.GetPropertyInfo <T>(prop);

        expr = Expression.Property(expr, pi);
        type = pi.PropertyType;

        Type             delegateType = typeof(Func <,>).MakeGenericType(typeof(T), type);
        LambdaExpression lambda       = Expression.Lambda(delegateType, expr, arg);
        string           methodName   = String.Empty;

        if (!orderByInfo.Initial && collection is IOrderedQueryable <T> )
        {
            methodName = orderByInfo.Direction == SortDirection.Ascending ? "ThenBy" : "ThenByDescending";
        }
        else
        {
            methodName = orderByInfo.Direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending";
        }

        //TODO: apply caching to the generic methodsinfos?
        return((IOrderedQueryable <T>) typeof(Queryable).GetMethods().Single(
                   method => method.Name == methodName &&
                   method.IsGenericMethodDefinition &&
                   method.GetGenericArguments().Length == 2 &&
                   method.GetParameters().Length == 2)
               .MakeGenericMethod(typeof(T), type)
               .Invoke(null, new object[] { collection, lambda }));
    }