我在VS2008动态LINQ示例中找到了一个示例,允许您使用类似sql的字符串(例如OrderBy(“Name, Age DESC”))进行排序。不幸的是,所包含的方法只适用于IQueryable<T>。有什么办法得到这个功能IEnumerable<T>?


当前回答

你可以这样做,对多个顺序

IOrderedEnumerable<JToken> sort;

if (query.OrderBys[0].IsDESC)
{
    sort = jarry.OrderByDescending(r => (string)r[query.OrderBys[0].Key]);
}
else
{
    sort = jarry.OrderBy(r =>
        (string) r[query.OrderBys[0].Key]); 
}

foreach (var item in query.OrderBys.Skip(1))
{
    if (item.IsDESC)
    {
        sort = sort.ThenByDescending(r => (string)r[item.Key]);
    }
    else
    {
        sort = sort.ThenBy(r => (string)r[item.Key]);
    }
}

其他回答

将List转换为IEnumerable或Iquerable,使用System.LINQ.Dynamic命名空间添加,然后你可以用逗号分隔的字符串提到OrderBy方法,OrderBy方法默认来自System.LINQ.Dynamic。

我试图这样做,但有问题与Kjetil Watnedal的解决方案,因为我不使用内联linq语法-我更喜欢方法风格的语法。我的具体问题是尝试使用自定义IComparer进行动态排序。

我的解决方案是这样的:

给定一个IQueryable查询,如下:

List<DATA__Security__Team> teams = TeamManager.GetTeams();
var query = teams.Where(team => team.ID < 10).AsQueryable();

给定一个运行时排序字段参数:

string SortField; // Set at run-time to "Name"

动态OrderBy看起来是这样的:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField));

这是使用一个叫做GetReflectedPropertyValue()的小助手方法:

public static string GetReflectedPropertyValue(this object subject, string field)
{
    object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null);
    return reflectedValue != null ? reflectedValue.ToString() : "";
}

最后一件事——我提到过我想让OrderBy使用自定义iccomparer——因为我想做自然排序。

要做到这一点,我只需要改变OrderBy为:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField), new NaturalSortComparer<string>());

有关NaturalSortComparer()的代码,请参阅这篇文章。

你可以像这样定义一个从string到Func<>的字典:

Dictionary<string, Func<Item, object>> SortParameters = new Dictionary<string, Func<Item, object>>()
{
    {"Rank", x => x.Rank}
};

像这样使用它:

yourList.OrderBy(SortParameters["Rank"]);

在这种情况下,您可以根据字符串动态排序。

你可以添加它:

public static IEnumerable<T> OrderBy( this IEnumerable<T> input, string queryString) {
    //parse the string into property names
    //Use reflection to get and sort by properties
    //something like

    foreach( string propname in queryString.Split(','))
        input.OrderBy( x => GetPropertyValue( x, propname ) );

    // I used Kjetil Watnedal's reflection example
}

GetPropertyValue函数来自Kjetil Watnedal的答案

问题是为什么?任何这样的排序都会在运行时抛出异常,而不是在编译时抛出异常(如D2VIANT的答案)。

如果你正在处理Linq to Sql, orderby是一个表达式树,它将被转换为Sql以执行。

感谢Maarten(在LINQ中使用PropertyInfo对象查询一个集合),我得到了这个解决方案:

myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();

在我的情况下,我在一个“ColumnHeaderMouseClick”(WindowsForm)上工作,所以只发现特定的列按下及其对应的PropertyInfo:

foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
    if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
    {}
}

OR

PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();

(确保你的列名称与对象属性匹配)

干杯