IOrderDenumerable y Programación defensiva
-
22-09-2019 - |
Pregunta
Me gusta la programación defensiva. Odio el lanzamiento de excepción, pero este no es el tema de mi pregunta.
Adapté una extensión a Linq para poder realizar un pedido con un nombre de columna
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
Con programación defensiva, este método devuelve el enumerable dado si el nombre de la columna no es válido.
Ahora necesito realizar un clasificación secundaria con entonces. Así que necesito esa firma:
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
Necesito devolver un iorderedenumerable. Mi problema es mantener mi función de programación defensiva: debo devolver el conjunto dado es que el nombre de la columna no es válido.
¿Hay una forma limpia de hacer esto? Todo lo que estoy pensando son un tipo de trucos:
- Use la reflexión al orden por la primera propiedad encontrada, que es arriesgada porque la propiedad puede no estar a la clasificación
- Implemente mi propio IOrderDenumerable, lo cual también es arriesgado porque realizo el pedido en IQueryable o Ilist, luego realizo otras operaciones de LINQ, por lo que temo los efectos secundarios.
Y consejo / sugerencia? Gracias
Solución
Puede hacer cualquier pedido. Si la columna no existe, simplemente deje su entrada enumerable como era antes. Para hacer esto, cree un selector de clave que devuelva el mismo valor para todos los elementos.
Ver ejemplo:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
static class Program
{
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression) where T : class
{
Func<T, Int32> keySelector = (elem) =>
{
PropertyInfo pi = typeof(T).GetProperty(sortExpression, typeof(Int32));
if (pi == null)
return 0; // return the same key for all elements
return Int32.Parse(pi.GetValue(elem, null).ToString());
};
return list.OrderBy(keySelector);
}
static void Main(string[] args)
{
// Create an array of strings to sort.
string[] fruits = { "apricot", "orange", "banana", "mango", "apple", "grape", "strawberry" };
// Sort by "column" Length
foreach (string s in fruits.OrderBy<string>("Length"))
Console.WriteLine(s);
Console.WriteLine();
// Sort by non-existing column
foreach (string s in fruits.OrderBy<string>("ength"))
Console.WriteLine(s);
Console.ReadKey();
}
}