我正在尝试动态地使用反射对给定的sortColumn(字符串)是否为null进行OrderBy,对sortColumn值进行ThenBy,对硬编码列进行ThenBy。像这样:
if (!String.IsNullOrEmpty(sortColumn)) {
var descending = sortDirection == "desc";
views = views.AsQueryable()
.OrderByNull<ToDoView>(sortColumn, true)//extension method
.OrderBy<ToDoView>(sortColumn, descending, true)//extension method
.ThenBy(v => v.summary ?? v.description).ToList();
}
使用其他SO答案,我能够使OrderBy扩展方法起作用:
public static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc, bool thenBy = false) {
string command = desc ? "OrderByDescending" : "OrderBy";
if (thenBy)
command = desc ? "ThenByDescending" : "ThenBy";
var type = typeof(TEntity);
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExpression = Expression.Lambda(propertyAccess, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery<TEntity>(resultExpression);
}
这是我的OrderByNull扩展方法:
public static IOrderedQueryable<TEntity> OrderByNull<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc, bool thenBy = false) {
string command = desc ? "OrderByDescending" : "OrderBy";
if (thenBy)
command = desc ? "ThenByDescending" : "ThenBy";
var type = typeof(TEntity);
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "p");
var target = Expression.Constant(null, type);
var equalsMethod = Expression.Call(Expression.Property(parameter, orderByProperty), "Equals", null, target);
var orderByExpression = Expression.Lambda(equalsMethod, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
source.Expression, Expression.Quote(orderByExpression));
return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery<TEntity>(resultExpression);
}
执行此扩展方法时,orderByExpression的计算结果为:
{p => p.listName.Equals(null)}
但是,当尝试设置resultExpression时会引发异常:
System.InvalidOperationException:'没有通用方法 类型'System.Linq.Queryable'上的'OrderByDescending'与 提供的类型实参和实参。类型参数不应该是 如果该方法是非泛型的,则提供。 '
我不太确定如何解决此问题,因为该表达式对我而言很合适。有什么想法吗?
================
这是我最后的OrderByNull扩展方法,在从可接受的答案中修复并使用等式逻辑解决NRE之后:
public static IOrderedQueryable<TEntity> OrderByNull<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc, bool thenBy = false) {
string command = desc ? "OrderByDescending" : "OrderBy";
if (thenBy)
command = desc ? "ThenByDescending" : "ThenBy";
var type = typeof(TEntity);
var property = type.GetProperty(orderByProperty);
var parameter = Expression.Parameter(type, "p");
var target = Expression.Constant(null, type);
var equalsMethod = Expression.Equal(Expression.Property(parameter, orderByProperty), Expression.Constant(null, typeof(object)));
var orderByExpression = Expression.Lambda(equalsMethod, parameter);
var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, typeof(bool) },
source.Expression, Expression.Quote(orderByExpression));
return (IOrderedQueryable<TEntity>)source.Provider.CreateQuery<TEntity>(resultExpression);
}
答案 0 :(得分:4)
在失败的情况下,您将property.PropertyType
(new Type[] { type, property.PropertyType }
)指定为被调用的泛型方法TKey
的{{1}}泛型类型参数,但是选择器lambda结果类型(应该与OrderBy<TSource, TKey>
相匹配的是TKey
,因此是例外。
要修复此问题,请更改
bool
到
new Type[] { type, property.PropertyType }
或更通用(可以在两种方法中同时使用)
new Type[] { type, typeof(bool) }