| | | 1 | | using System.Reflection; |
| | | 2 | | |
| | | 3 | | // ReSharper disable once CheckNamespace |
| | | 4 | | namespace Microsoft.EntityFrameworkCore; |
| | | 5 | | |
| | | 6 | | /// <summary>Sorting helpers for <see cref="IQueryable{T}"/> driven by request values.</summary> |
| | | 7 | | public static class DataCollectionExtensions |
| | | 8 | | { |
| | | 9 | | /// <summary> |
| | | 10 | | /// Sorts by the property or field named <paramref name="propertyName"/> (case-insensitive). The query is returned |
| | | 11 | | /// unsorted when the name is blank or <typeparamref name="T"/> has no such member, so a request value can be passed |
| | | 12 | | /// </summary> |
| | | 13 | | /// <typeparam name="T">The row type.</typeparam> |
| | | 14 | | /// <param name="source">The query.</param> |
| | | 15 | | /// <param name="propertyName">The member to sort by.</param> |
| | | 16 | | /// <param name="dir">The direction; descending by default.</param> |
| | | 17 | | /// <returns>The sorted query.</returns> |
| | | 18 | | public static IQueryable<T> OrderByProperty< T >( this IQueryable<T> source, string? propertyName, OrderDirection? d |
| | | 19 | | { |
| | 0 | 20 | | ArgumentNullException.ThrowIfNull( source ); |
| | | 21 | | |
| | 0 | 22 | | if ( string.IsNullOrWhiteSpace( propertyName ) ) { return source; } |
| | | 23 | | |
| | | 24 | | |
| | | 25 | | const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase; |
| | 0 | 26 | | var member = (MemberInfo?) typeof( T ).GetProperty( propertyName, flags ) ?? typeof( T ).GetField |
| | | 27 | | |
| | 0 | 28 | | if ( member is null ) { return source; } |
| | | 29 | | |
| | | 30 | | |
| | 0 | 31 | | var parameter = Expression.Parameter( typeof( T ), "x" ); |
| | 0 | 32 | | var selector = Expression.MakeMemberAccess( parameter, member ); |
| | 0 | 33 | | var method = dir == OrderDirection.Descending ? nameof( Queryable.OrderByDescending ) : nameof( Queryable.Ord |
| | | 34 | | |
| | | 35 | | |
| | 0 | 36 | | var call = Expression.Call( typeof( Queryable ), method, [ typeof( T ), selector.Type ], source.Expression, |
| | 0 | 37 | | Expression.Quote( Expression.Lambda( selector, parameter ) ) ); |
| | | 38 | | |
| | | 39 | | |
| | 0 | 40 | | return source.Provider.CreateQuery<T>( call ); |
| | | 41 | | } |
| | | 42 | | |
| | | 43 | | /// <summary>Sorts the rows themselves (for queries of simple values).</summary> |
| | | 44 | | /// <typeparam name="T">The row type.</typeparam> |
| | | 45 | | /// <param name="source">The query.</param> |
| | | 46 | | /// <param name="dir">The direction; ascending by default.</param> |
| | | 47 | | /// <returns>The sorted query.</returns> |
| | | 48 | | public static IQueryable<T> OrderByDirection< T >( this IQueryable<T> source, OrderDirection? dir = OrderDirection.A |
| | 0 | 49 | | => dir == OrderDirection.Descending ? source.OrderByDescending( x => x ) : source.OrderBy( x => x ); |
| | | 50 | | } |