【问题标题】:Runtime Sorting and Types with Linq使用 Linq 进行运行时排序和类型
【发布时间】:2021-06-14 13:48:02
【问题描述】:

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

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

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

我首先得到IEnumerable 的类型。我为此创建了一个方法。我不会在这里讨论这个细节。它已经过测试并且确实返回了正确的类型。

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;

我尝试创建一个新的 Typed 列表(因为我知道类型),以便更准确地推断 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; 
                        
                        
                        

我的想法已经用完了。

【问题讨论】:

  • 你使用dynamic而不是object的原因是什么? Type dataType = TypeService.GetType(dataToSort); 当你说可以有任何类型的对象时,只给你一个基于整个列表的类型?
  • 参数可能是 List&lt;KeyValuePair&gt;,它是一个值类型而不是引用类型。这打破了IEnumerable&lt;object&gt; 类型。不确定这是否仍然是这种情况(传递值类型)但是...
  • 那么您在列表中传递的所有对象是否具有相同的属性或者您要按什么排序?
  • TypeService.GetType() 返回dynamic 的底层证券。因此,如果 IEnumerable.&lt;dynamic&gt; dataSort 原来是 IEnumerable&lt;Person&gt;' at runtime TypeService.GetType(dataToSort)` 将返回 Type dataType = Person。
  • 对象列表可以是任何具有任何属性名称的东西。我使用反射来验证(我从 OP 中省略以减少混乱)sortArgs 中定义的字段名称对于 TypeService.GetType() 方法返回的类型有效。

标签: c# linq linq-to-entities


【解决方案1】:

要从List&lt;T&gt; 创建IOrderedIEnumerable 而不操纵顺序,您可以通过执行以下操作来执行 noop 排序:

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

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

【讨论】:

  • 我只想补充一点,如果您不使用方法语法,它看起来像... from dataItem in dataToSort orderby 1 select dataItem; 感谢 Dominik 的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 2021-06-30
  • 2012-01-28
  • 2010-12-31
  • 2017-02-22
相关资源
最近更新 更多