使用 Linq 进行运行时排序和类型

Runtime Sorting and Types with Linq

我看过很多文章,它们似乎都在讨论我遇到的问题,但 none 提供了解决问题的实际方法。也就是说,他们都让我得到了大约 98% 的解决方案,只是在一些小细节上失败了。

我有一个在 运行 时间收集的 IEnumerable。这个 IEnumerable 可以是任何东西。直到 运行 时间我才会知道。但是,我需要根据作为参数提供的 KeyValuePair 对象列表中的 属性 名称列表和排序方向对其进行排序。

public static void SortData(IEnumerable<dynamic> dataToSort,  List<KeyValuePair<string, string>> sortArgs)
{
}

我首先得到IEnumerable的Type。我为此创建了一个方法。我不会在这里详细介绍。它已经过测试 return 正确的类型。

public static void SortData(IEnumerable<dynamic> dataToSort, List<KeyValuePair<string, string>> sortArgs)
{
    Type dataType = TypeService.GetType(data);  
}

然后我尝试创建一个初始 IOrderedEnumerable,我可以将 sortArgs 排序应用于。

public static void SortData(IEnumerable<dynamic> dataToSort,  List<KeyValuePair<string, string>> sortArgs)
{
    Type dataType   = TypeService.GetType(dataToSort);  

    // Create IOrderedEnumerable
    //
    var query       = from dataItem in dataToSort
                      orderby // ?????  
                      select dataItem;

    // apply sortArgs to IOrderedEnumerable
    //
    for(int argIDX = 0; argIDX < sortArgs.Count; argIDX++)
    {
        var arg             = sortArgs[argIDX];
        var sortField       = arg.Key.Trim();
        var sortDirection   = arg.Value.Trim().ToUpper();

        if(argIDX == 0)
        {
            if(sortDirection == "DESC")
            {
                query = query.OrderByDescending(e => e.GetType().GetProperty(sortField).GetValue(e));
            }
            else
            {
                query = query.OrderBy(e => e.GetType().GetProperty(sortField).GetValue(e));
            }
        }
        else
        {
            if(sortDirection == "DESC")
            {
                query = query.ThenByDescending(e => e.GetType().GetProperty(sortField).GetValue(e));
            }
            else
            {
                query = query.ThenBy(e => e.GetType().GetProperty(sortField).GetValue(e));
            }
        }
    }

    // After applying the sort retreive the contents
    //
    dataToSort = query.ToList();                      
}

看来我已经掌握了对原始 dataToSort 参数进行排序所需的所有信息。但是定义一个 属性 来初始化 IOrderedEnumerable 是我无法理解的。

我已经尝试了很多不同的技术,我已经阅读过...

var query       = from dataItem in dataToSort
                  orderby ( X => 1)    //ERR: The type of one of the expressions in the OrderBy clause is incorrect. Type inference failed in the call to 'OrderBy'.
                  select dataItem;

我尝试创建一个新的类型化列表(因为我知道类型),以便可以更准确地推断 OrderBy 子句中的表达式。

var typedDataToSort = new List<dataType>(); //ERR: dataType is a variable used like a type
foreach(var item in dataToSort)
{
    typedDataToSort.Add( item );
}

        

我已尝试获取 属性 的 PropertyInfo 以进行排序..

PropertyInfo propInfo = dataType.GetProperty(dataValueField);
var query             = from dataItem in dataToSort
                        orderby (x => propInfo.GetValue(x, null)) //ERR: The type of one of the expressions in the OrderBy clause is incorrect. Type inference failed in the call to 'OrderBy'. Of couse this could not work since `dataType` is an INSTANCE of
                        select dataItem; 
                        
                        
                        

我刚刚 运行 没主意了。

要从 List<T> 创建一个 IOrderedIEnumerable 而无需操纵顺序,您只需执行 noop 排序,方法如下:

var myList = new List<String>(){"test1", "test3", "test2"}
IOrderedIEnumerable<String> query = myList.OrderBy(x => 1);

IEnumerable 也是如此 - 但是您必须确保 IEnumerable 的底层类型为每次迭代提供稳定的顺序。