Ordinare una lista in memoria in base ad una proprietà per nome

Scritto da  Alessandro Mostarda il giovedì 1 luglio 2010  •  Linguaggio: C#,VB   • Livello: 200


Se abbiamo necessità di ordinare una lista per una proprietà della quale, però, abbiamo il nome in formato stringa, possiamo utilizzare uno dei seguenti extension method:

C#


using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

public static class OrderByExpressions
{

//Order by che accetta il nome della proprietà in input
public static IOrderedQueryable<T> OrderBy<T>(this IEnumerable<T> list, string fieldName)
{
return OrderBy(list, fieldName, false);
}

//Order by Descending che accetta il nome della proprietà in input
public static IOrderedQueryable<T> OrderByDescending<T>(this IEnumerable<T> list, string fieldName)
{
return OrderBy(list, fieldName, true);
}

//Then by che accetta il nome della proprietà in input
public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> list, string fieldName)
{
return ThenBy(list, fieldName, false);
}

//Then by Descending che accetta il nome della proprietà in input
public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> list, string fieldName)
{
return ThenBy(list, fieldName, true);
}

//Order che accetta input un elenco di nomi di proprietà e il tipo di ordinamaneto(False = Descending, True = Ascenbing)
public static IOrderedQueryable<T> Order<T>(this IEnumerable<T> list, Dictionary<string, bool> fields)
{
IOrderedQueryable<T> temp = null;
bool first = true;
foreach (KeyValuePair<string, bool> field in fields)
{
if (first)
{
temp = OrderBy(list, field.Key, field.Value);
first = false;
} else {
temp = ThenBy(temp, field.Key, field.Value);
}
}
return temp;
}

private static IOrderedQueryable<T> OrderBy<T>(IEnumerable<T> list, string fieldName, bool descending)
{
var orderExpression = GetOrderExpression(list, fieldName);
if (descending)
{
return list.AsQueryable().OrderByDescending(orderExpression);
} else {
return list.AsQueryable().OrderBy(orderExpression);
}
}

private static IOrderedQueryable<T> ThenBy<T>(IOrderedQueryable<T> list, string fieldName, bool descending)
{
var orderExpression = GetOrderExpression(list, fieldName);
if (descending)
{
return list.ThenByDescending(orderExpression);
} else {
return list.ThenBy(orderExpression);
}
}

private static Expression<Func<T, object>> GetOrderExpression<T>(IEnumerable<T> list, string fieldName)
{
var parameterExpression = Expression.Parameter(typeof(T), "item");
var memberExpression = Expression.Property(parameterExpression, fieldName);
var expression = Expression.Convert(memberExpression, typeof(object));
return Expression.Lambda<Func<T, object>>(expression, parameterExpression);
}
}


VB.NET

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Text
Imports System.Runtime.CompilerServices

Public Module OrderByExpressions

'Order by che accetta il nome della proprietà in input
<Extension()> Public Function OrderBy(Of T)(ByVal list As IEnumerable(Of T), ByVal fieldName As String) As IOrderedQueryable(Of T)
Return OrderBy(list, fieldName, False)
End Function

'Order by Descending che accetta il nome della proprietà in input
<Extension()> Public Function OrderByDescending(Of T)(ByVal list As IEnumerable(Of T), ByVal fieldName As String) As IOrderedQueryable(Of T)
Return OrderBy(list, fieldName, True)
End Function

'Then by che accetta il nome della proprietà in input
<Extension()> Public Function ThenBy(Of T)(ByVal list As IOrderedQueryable(Of T), ByVal fieldName As String) As IOrderedQueryable(Of T)
Return ThenBy(list, fieldName, False)
End Function

'Then by Descending che accetta il nome della proprietà in input
<Extension()> Public Function ThenByDescending(Of T)(ByVal list As IOrderedQueryable(Of T), ByVal fieldName As String) As IOrderedQueryable(Of T)
Return ThenBy(list, fieldName, True)
End Function

'Order che accetta input un elenco di nomi di proprietà e il tipo di ordinamaneto(False = Descending, True = Ascenbing)
<Extension()> Public Function Order(Of T)(ByVal list As IEnumerable(Of T), ByVal fields As Dictionary(Of String, Boolean)) As IOrderedQueryable(Of T)
Dim temp As IOrderedQueryable(Of T) = Nothing
Dim first As Boolean = True
For Each field As KeyValuePair(Of String, Boolean) In fields
If first Then
temp = OrderBy(list, field.Key, field.Value)
first = False
Else
temp = ThenBy(temp, field.Key, field.Value)
End If
Next
Return temp
End Function

Private Function OrderBy(Of T)(ByVal list As IEnumerable(Of T), ByVal fieldName As String, ByVal descending As Boolean) As IOrderedQueryable(Of T)
Dim orderExpression = GetOrderExpression(list, fieldName)
If descending Then
Return list.AsQueryable().OrderByDescending(orderExpression)
Else
Return list.AsQueryable().OrderBy(orderExpression)
End If
End Function

Private Function ThenBy(Of T)(ByVal list As IOrderedQueryable(Of T), ByVal fieldName As String, ByVal descending As Boolean) As IOrderedQueryable(Of T)
Dim orderExpression = GetOrderExpression(list, fieldName)
If descending Then
Return list.ThenByDescending(orderExpression)
Else
Return list.ThenBy(orderExpression)
End If
End Function

Private Function GetOrderExpression(Of T)(ByVal list As IEnumerable(Of T), ByVal fieldName As String) As Expression(Of Func(Of T, Object))
Dim parameterExpression = Expression.Parameter(GetType(T), "item")
Dim memberExpression = Expression.Property(parameterExpression, fieldName)
Dim express = Expression.Convert(memberExpression, GetType(Object))
Return Expression.Lambda(Of Func(Of T, Object))(express, parameterExpression)
End Function
End Module


Tags: Linq

 
x