我使用的是Entity Framework,ASP.NET和C#3.5 我借用以下代码来使用GridView中的sortExpression而不是实体的属性进行排序:
public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
{
string[] sortParts = sortExpression.Split(' ');
var param = Expression.Parameter(typeof(T), string.Empty);
var property = Expression.Property(param, sortParts[0]);
var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);
if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
{
return source.AsQueryable<T>().OrderByDescending(sortLambda);
}
return source.AsQueryable<T>().OrderBy(sortLambda);
}
问题是LINQ to Entities不支持转换为对象。而不是Func,我需要实际的返回类型而不是对象。我找到了如何做到这一点:
public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
{
string[] sortParts = sortExpression.Split(' ');
var param = Expression.Parameter(typeof(T), string.Empty);
var property = Expression.Property(param, sortParts[0]);
// NEW CODE HERE
Type propertyType = property.Type;
Type lambdaType = typeof(Func<,>).MakeGenericType(typeof(T), propertyType);
var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, propertyType), param);
//var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);
if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
{
return source.AsQueryable<T>().OrderByDescending(sortLambda);
}
return source.AsQueryable<T>().OrderBy(sortLambda);
}
现在的问题是,如果我有一个Int32,它将不会转换为对象,它仍然是返回类型。我这样解决了这个问题:
public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression)
{
string[] sortParts = sortExpression.Split(' ');
var param = Expression.Parameter(typeof(T), string.Empty);
var property = Expression.Property(param, sortParts[0]);
// New code here
Type propertyType = property.Type;
Type lambdaType = typeof(Func<,>).MakeGenericType(typeof(T), propertyType);
// NEWEST CODE HERE
var sortLambda = Expression.Lambda(lambdaType, Expression.Convert(property, propertyType), param);
//var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, propertyType), param);
//var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);
if (sortParts.Length > 1 && sortParts[1].Equals("desc", StringComparison.OrdinalIgnoreCase))
{
return source.AsQueryable<T>().OrderByDescending(sortLambda);
}
return source.AsQueryable<T>().OrderBy(sortLambda);
}
然而,这不再编译。错误是:
无法从用法推断出方法'System.Linq.Enumerable.OrderByDescending(System.Collections.Generic.IEnumerable,System.Func)'的类型参数。尝试显式指定类型参数。
问题在于我不想明确指定类型参数。
有没有人知道如何解决这个问题或者无论如何从“propertyType”推断出TResult类型?
答案 0 :(得分:1)
使用here的refinement here方法应该可以满足您的需求。必要时,它使用反射来做中间的内脏,但它的工作原理。另请注意,Expression.GetFuncType
和Expression.GetActionType
可以避免您的方法中的一些工作。