使用 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
的底层类型为每次迭代提供稳定的顺序。
我看过很多文章,它们似乎都在讨论我遇到的问题,但 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
的底层类型为每次迭代提供稳定的顺序。