Poniamo di avere una collection di nostre custom entities che implementa IEnumerable<T> e poniamo di doverla ordinare rispetto ad una proprietà. Se ad esempio la entity rappresenta una riga ordine potremmo dover ordinare le righe per codice prodotto; con LINQ faremmo una cosa del genere:

   1: public void SortRowsBySKU(IEnumerable<OrderRow> rows)
   2: {
   3:     return from item in rows
   4:         orderby item.SKU ascending
   5:         select item;
   6: }

Linq è decisamente vantaggioso, e ci risparmia un bel po' di lavoro. Ma poniamo per un momento di dover ordinare ora la stessa collection per la proprietà Price, e magari dare all'utente la possibilità di scegliere la colonna a runtime. Ovviamente sarebbe una pessima idea creare una query per proprietà. Il codice diventerebbe inutilmente proolisso e poco manutenibile. Per parametrizzare la clausola di orderby potremmo invece usare la reflection come segue:

   1: public void SortRows(IEnumerable<OrderRow> rows, string sortExpression)
   2: {
   3:     return from item in rows
   4:         orderby item.GetPropertyValue(sortExpression) ascending
   5:         select item;
   6: }

Il metodo GetPropertyValue è un ExtensionMethod che viene da una classe di utilità relativa la reflection e semplicemente ottiene il valore di una proprietà di un oggetto passata come argomento di tipo stringa:

   1: public static class ReflectionExtensions
   2: {
   3:     public static object GetPropertyValue(this object value, string propertyName)
   4:     {
   5:         Type type = value.GetType();
   6:         PropertyInfo property = type.GetProperty(propertyName);
   7:         return property.GetValue(value, null);
   8:     }
   9: }

L'esempio in questione probabilmente è poco significativo perchè chiunque di voi avrà da obbiettare che sarebbe meglio fare l'ordinamento direttamente nella istruzione SQL che estrae i valori e io non posso che essere daccordo su questo. Ma sono certo che esistono un buon numero di casi in cui avendo a disposizione un semplice IEnumerable<T> sia necessario ordinarlo per una specifica proprietà. Mi raccomando però, questo esempio si applica solo a LINQ to objects.

Technorati Tag: ,

Aggiungi Commento