113 lines
5.0 KiB
C#
113 lines
5.0 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace CloudBuilder.Core.Extensions
|
|
{
|
|
/// <summary>
|
|
/// 集合类型字符串排序操作类
|
|
/// </summary>
|
|
/// <typeparam name="T">集合项类型</typeparam>
|
|
public static class CollectionPropertySorter<T>
|
|
{
|
|
// ReSharper disable StaticFieldInGenericType
|
|
private static readonly ConcurrentDictionary<string, LambdaExpression> Cache = new ConcurrentDictionary<string, LambdaExpression>();
|
|
|
|
/// <summary>
|
|
/// 按指定的属性名称对<see cref="IEnumerable{T}"/>序列进行排序
|
|
/// </summary>
|
|
/// <param name="source"><see cref="IEnumerable{T}"/>序列</param>
|
|
/// <param name="propertyName">属性名称</param>
|
|
/// <param name="sortDirection">排序方向</param>
|
|
public static IOrderedEnumerable<T> OrderBy(IEnumerable<T> source, string propertyName, ListSortDirection sortDirection)
|
|
{
|
|
propertyName.CheckNotNullOrEmpty("propertyName");
|
|
dynamic expression = GetKeySelector(propertyName);
|
|
dynamic keySelector = expression.Compile();
|
|
return sortDirection == ListSortDirection.Ascending
|
|
? Enumerable.OrderBy(source, keySelector)
|
|
: Enumerable.OrderByDescending(source, keySelector);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按指定的属性名称对<see cref="IOrderedEnumerable{T}"/>进行继续排序
|
|
/// </summary>
|
|
/// <param name="source"><see cref="IOrderedEnumerable{T}"/>序列</param>
|
|
/// <param name="propertyName">属性名称</param>
|
|
/// <param name="sortDirection">排序方向</param>
|
|
public static IOrderedEnumerable<T> ThenBy(IOrderedEnumerable<T> source, string propertyName, ListSortDirection sortDirection)
|
|
{
|
|
propertyName.CheckNotNullOrEmpty("propertyName");
|
|
dynamic expression = GetKeySelector(propertyName);
|
|
dynamic keySelector = expression.Compile();
|
|
return sortDirection == ListSortDirection.Ascending
|
|
? Enumerable.ThenBy(source, keySelector)
|
|
: Enumerable.ThenByDescending(source, keySelector);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按指定的属性名称对<see cref="IQueryable{T}"/>序列进行排序
|
|
/// </summary>
|
|
/// <param name="source">IQueryable{T}序列</param>
|
|
/// <param name="propertyName">属性名称</param>
|
|
/// <param name="sortDirection">排序方向</param>
|
|
/// <returns></returns>
|
|
public static IOrderedQueryable<T> OrderBy(IQueryable<T> source, string propertyName, ListSortDirection sortDirection)
|
|
{
|
|
propertyName.CheckNotNullOrEmpty("propertyName");
|
|
dynamic keySelector = GetKeySelector(propertyName);
|
|
return sortDirection == ListSortDirection.Ascending
|
|
? Queryable.OrderBy(source, keySelector)
|
|
: Queryable.OrderByDescending(source, keySelector);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 按指定的属性名称对<see cref="IOrderedQueryable{T}"/>序列进行排序
|
|
/// </summary>
|
|
/// <param name="source">IOrderedQueryable{T}序列</param>
|
|
/// <param name="propertyName">属性名称</param>
|
|
/// <param name="sortDirection">排序方向</param>
|
|
/// <returns></returns>
|
|
public static IOrderedQueryable<T> ThenBy(IOrderedQueryable<T> source, string propertyName, ListSortDirection sortDirection)
|
|
{
|
|
propertyName.CheckNotNullOrEmpty("propertyName");
|
|
dynamic keySelector = GetKeySelector(propertyName);
|
|
return sortDirection == ListSortDirection.Ascending
|
|
? Queryable.ThenBy(source, keySelector)
|
|
: Queryable.ThenByDescending(source, keySelector);
|
|
}
|
|
|
|
private static LambdaExpression GetKeySelector(string keyName)
|
|
{
|
|
Type type = typeof(T);
|
|
string key = type.FullName + "." + keyName;
|
|
if (Cache.ContainsKey(key))
|
|
{
|
|
return Cache[key];
|
|
}
|
|
ParameterExpression param = Expression.Parameter(type);
|
|
string[] propertyNames = keyName.Split('.');
|
|
Expression propertyAccess = param;
|
|
foreach (string propertyName in propertyNames)
|
|
{
|
|
PropertyInfo property = type.GetProperty(propertyName);
|
|
if (property == null)
|
|
{
|
|
throw new Exception(string.Format("指定对象中不存在名称为“{0}”的属性。", propertyName));
|
|
}
|
|
type = property.PropertyType;
|
|
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
|
|
}
|
|
LambdaExpression keySelector = Expression.Lambda(propertyAccess, param);
|
|
Cache[key] = keySelector;
|
|
return keySelector;
|
|
}
|
|
}
|
|
}
|