动态创建排序Lambda表达式
本文关键字:表达式 Lambda 排序 创建 动态 | 更新日期: 2023-09-27 18:24:57
我想使用lambda表达式按照任意列/字段名对任意实体类型的IEnumerable进行排序。
我有这样的分类功能:
public static IEnumerable<T> SortByFieldName<T>(IEnumerable<T> target, string sortPropertyName, string sortDirection)
{
if (!String.IsNullOrEmpty(sortPropertyName))
{
Expression<Func<T, object>> sortExpression = GetSortLambda<T>(sortPropertyName);
switch (sortDirection.ToLower())
{
case "a":
return target.AsQueryable<T>().OrderBy(sortExpression);
case "d":
return target.AsQueryable<T>().OrderByDescending(sortExpression);
default:
return target;
}
}
return target;
}
用这个函数创建表达式(从这里的另一个答案修改而来)
public static Expression<Func<T,object>> GetSortLambda<T>(string propertyPath)
{
var param = Expression.Parameter(typeof(T), "p");
var parts = propertyPath.Split('.');
Expression parent = param;
foreach (var part in parts)
{
parent = Expression.Property(parent, part);
}
var sortExpression = Expression.Lambda<Func<T, object>>(parent, param);
return sortExpression;
}
对于解析为字符串的任何属性路径,这都可以正常工作,但对于Integers(对于Boolean则不太常见),会生成以下错误(在Int32属性的情况下):
"System.Int32"类型的表达式不能用于返回类型"System.Object"
我认为,这是因为作为返回的表达式
Expression<Func<T,object>>
但我不知道如何克服这一点——object
应该涵盖所有的属性类型,不是吗?
我可能可以通过反射来实现这一点,获得目标列的PropertyInfo(从而获得类型),但如果可能的话,我总是选择避免反射。
感谢您的指导/建议!
如果处理整数或日期等值类型,则可能需要Convert
表达式:
public static Expression<Func<T, object>> GetSortLambda<T>(string propertyPath)
{
var param = Expression.Parameter(typeof(T), "p");
var parts = propertyPath.Split('.');
Expression parent = param;
foreach (var part in parts)
{
parent = Expression.Property(parent, part);
}
if (parent.Type.IsValueType)
{
var converted = Expression.Convert(parent, typeof(object));
return Expression.Lambda<Func<T, object>>(converted, param);
}
else
{
return Expression.Lambda<Func<T, object>>(parent, param);
}
}