Reflection 用IQueryable反射

Reflection 用IQueryable反射,reflection,iqueryable,propertyinfo,Reflection,Iqueryable,Propertyinfo,我正在研究并尝试为IQueryable创建一个扩展方法,该方法根据对象的任意属性对其进行排序 public static class IQueryableExtender { public static IQueryable<TSource> Sort<TSource>(this IQueryable<TSource> query, string orderProperty, string sortDirection = "asc") {

我正在研究并尝试为IQueryable创建一个扩展方法,该方法根据对象的任意属性对其进行排序

public static class IQueryableExtender

{

public static IQueryable<TSource> Sort<TSource>(this IQueryable<TSource> query, string orderProperty, string sortDirection = "asc")      
{

    var elementType = query.ElementType;

    var propertyInfo = elementType.GetProperty(orderProperty);
    if (propertyInfo == null)
    {
         throw new ArgumentException(string.Format("{0} is not a property on {1}", orderProperty, elementType.Name));
    }


    switch (sortDirection.ToLower())
    {
       case "asc":
       case "ascending":
           return query.OrderBy(x => propertyInfo.GetValue(x, null));
           break;
       case "desc":
       case "descending":
           return query.OrderByDescending(x => propertyInfo.GetValue(x, null));
           break;
    }

    return query;
}
}
公共静态类IQueryableExtender
{
公共静态IQueryable排序(此IQueryable查询,字符串orderProperty,字符串sortDirection=“asc”)
{
var elementType=query.elementType;
var propertyInfo=elementType.GetProperty(orderProperty);
如果(propertyInfo==null)
{
抛出新ArgumentException(string.Format(“{0}不是{1}”上的属性,orderProperty,elementType.Name));
}
开关(sortDirection.ToLower())
{
案例“asc”:
案例“升序”:
返回query.OrderBy(x=>propertyInfo.GetValue(x,null));
打破
案例“desc”:
案例“下降”:
返回query.OrderByDescending(x=>propertyInfo.GetValue(x,null));
打破
}
返回查询;
}
}
我在调用该方法时遇到此错误。我想这与IQueryable有关,它还没有执行和检索任何对象

LINQ to Entities无法识别方法
System.Object GetValue(System.Object,System.Object[])
,此方法无法转换为存储表达式

我可以通过在IQueryable上执行ToList来解决这个问题,但是我在扩展方法中检索数据,这不是我想要的


这可以解决吗?

当您对IQueryable执行LINQ操作时,LINQ to Entities会尝试在数据库中运行查询。在您的
案例“asc”
中,您执行query.OrderBy,LINQ to Entities将其解释为“将其转换为SQL”,但由于您使用了反射调用,而反射调用不知道如何转换为SQL,因此失败

您可以执行query.AsEnumerable().OrderBy(…)。这样做的一个效果是,当OrderBy操作开始运行时,将执行查询的其余部分,以便提供数据

您不必使用这些反射技巧,只需使用OrderBy和OrderByDescending方法就可以了,这些方法设计用于获取委托以提取排序值。(
items.OrderBy(item=>item.Property)
)。您缺少的是在同一个方法中指定升序或降序的功能,但我只需要执行以下两种方法:

public static IOrderedQueryable<TSource> OrderByAscDesc<TSource, TKey>(
    this IQueryable<TSource> source,
    Expression<Func<TSource, TKey>> keySelector, bool isAsc
) {
    return (isAsc ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
}

public static IOrderedQueryable<TSource> OrderByAscDesc<TSource, TKey>(
    this IQueryable<TSource> source,
    Func<TSource, TKey> keySelector, bool ascDesc
) {
    return (isDesc ? source.OrderBy(keySelector) : source.OrderByDescending(keySelector);
}
公共静态IOrderedQueryable OrderByAscDesc(
这是可靠的消息来源,
表达式键选择器
) {
return(isAsc?source.OrderBy(keySelector):source.OrderByDescending(keySelector);
}
公共静态IOrderedQueryable OrderByAscDesc(
这是可靠的消息来源,
Func键选择器,布尔ascDesc
) {
return(isDesc?source.OrderBy(keySelector):source.OrderByDescending(keySelector);
}

谢谢你的回答。这不是我想要的。我忽略了我正在使用MVC,我从视图中获取了要排序的属性的名称。因此我想要一种方法,在该方法中,我可以从对象中获取参数并反映属性值,然后对其进行排序。这意味着我不需要任何if语句来选择在if语句中使用哪个属性。这更有意义。在使用OrderBy之前添加AsEnumerable()应该可以解决这个问题。