/// <summary>
/// 实现动态排序
/// 来源博客园的一个大神,具体实现原理是利用实体和排序字段自动生成一个表达式
/// 再利用IQuerable的方法实现
/// 有一部分比较像微软的源码 ZhangQC 2016.10.20
/// </summary>
public static class DynamicOrder
{
#region Private 表达式树
/// <summary>
/// 构建表达式树 结果类似于 j=>j.Name
/// </summary>ZhangQc 2016.10.20
/// <typeparam name="TEntity"></typeparam>
/// <param name="propertyName"></param>
/// <param name="resultType"></param>
/// <returns></returns>
private static LambdaExpression GenerateSelector<TEntity>(String propertyName, out Type resultType) where TEntity : class
{
PropertyInfo property;
Expression propertyAccess;
var parameter = Expression.Parameter(typeof(TEntity), "j");
if (propertyName.Contains(‘.‘))
{
String[] childProperties = propertyName.Split(‘.‘);
property = typeof(TEntity).GetProperty(childProperties[0]);
propertyAccess = Expression.MakeMemberAccess(parameter, property);
for (int i = 1; i < childProperties.Length; i++)
{
property = property.PropertyType.GetProperty(childProperties[i]);
propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
}
}
else
{
property = typeof(TEntity).GetProperty(propertyName);
propertyAccess = Expression.MakeMemberAccess(parameter, property);
}
resultType = property.PropertyType;
return Expression.Lambda(propertyAccess, parameter);
}
/// <summary>
/// 生成方法调用
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="source"></param>
/// <param name="methodName"></param>
/// <param name="fieldName"></param>
/// <returns></returns>
private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, String fieldName) where TEntity : class
{
Type type = typeof(TEntity);
Type selectorResultType;
LambdaExpression selector = GenerateSelector<TEntity>(fieldName, out selectorResultType);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
new Type[] { type, selectorResultType },
source.Expression, Expression.Quote(selector));
return resultExp;
}
#endregion
public static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "OrderBy", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> OrderByDescending<TEntity>(this IQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "OrderByDescending", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> ThenBy<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "ThenBy", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> ThenByDescending<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "ThenByDescending", fieldName);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
public static IOrderedQueryable<TEntity> OrderUsingSortExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression) where TEntity : class
{
String[] orderFields = sortExpression.Split(‘,‘);
IOrderedQueryable<TEntity> result = null;
for (int currentFieldIndex = 0; currentFieldIndex < orderFields.Length; currentFieldIndex++)
{
String[] expressionPart = orderFields[currentFieldIndex].Trim().Split(‘ ‘);
String sortField = expressionPart[0];
Boolean sortDescending = (expressionPart.Length == 2) && (expressionPart[1].Equals("DESC", StringComparison.OrdinalIgnoreCase));
if (sortDescending)
{
result = currentFieldIndex == 0 ? source.OrderByDescending(sortField) : result.ThenByDescending(sortField);
}
else
{
result = currentFieldIndex == 0 ? source.OrderBy(sortField) : result.ThenBy(sortField);
}
}
return result;
}
//使用方法
// var query = (from d in ((VinnoTech.Gaia2.DB.g2_dsource[])result)
// join p in WebApiApplication.entities.g2_propnames
// on d.dsource_item equals p.prop_name
// orderby sidx
// select new
// {
// d.dsource_id,
// d.dsource_name,
// dsource_item = p.prop_description,
// d.dsource_description,
// dsource_status = d.dsource_status == "1" ? "启用" : "禁用",
// d.dsource_expiredday,
// dsource_alarmhigh = (d.dsource_alarmhigh == -65535 || d.dsource_alarmhigh == 65535) ? "未禁用" : d.dsource_alarmhigh.ToString(),
// dsource_alarmlow = (d.dsource_alarmlow == -65535 || d.dsource_alarmhigh == 65535) ? "未禁用" : d.dsource_alarmhigh.ToString(),
// dsource_alarmdeltadata = (d.dsource_alarmdeltadata == -65535 || d.dsource_alarmhigh == 65535) ? "未禁用" : d.dsource_alarmhigh.ToString(),
// dsource_alarmidle = (d.dsource_alarmidle == -65535 || d.dsource_alarmhigh == 65535) ? "未禁用" : d.dsource_alarmhigh.ToString(),
// d.dsource_formula,
// dsource_updatetime = d.dsource_updatetime.ToString("yyyy-MM-dd HH:mm:ss")
// }).AsQueryable();
//page = page <= query.Count() / rows + 1 ? page : 1;
//query = query.OrderUsingSortExpression("dsource_name asc,dsource_item desc").Skip(rows * (page - 1)).Take(rows);
}