Programação integral e defensiva
-
22-09-2019 - |
Pergunta
Gosto de programação defensiva. Eu odeio uma exceção ao arremesso, mas esse não é o assunto da minha pergunta.
Adaptei uma extensão ao LINQ para poder executar uma ordem com um nome de coluna
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
Com programação defensiva, esse método retorna o enumerável dado se o nome da coluna não for válido.
Agora eu preciso realizar um classificação secundária com então. Então eu preciso dessa assinatura:
public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
Eu preciso devolver um eu ordenado. Meu problema é manter meu recurso de programação defensiva: devo devolver o conjunto fornecido é o nome da coluna é inválido.
Existe uma maneira limpa de fazer isso? Tudo o que estou pensando são tipo de truques:
- Use a reflexão para encomendar pela primeira propriedade encontrada, o que é arriscado porque a propriedade pode não estar classificada
- Implementar minha própria ordem de referência, o que também é arriscado porque eu executo pedidos em iQueryable ou Ilist, depois realizo outras operações do LINQ, por isso temo os efeitos colaterais.
E conselho / sugestão? Obrigado
Solução
Você pode fazer qualquer pedido. Se a coluna não existir, deixe sua entrada enumerável como era antes. Para fazer isso, crie o seletor de chaves que retorne o mesmo valor para todos os elementos.
Consultar exemplo:
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();
}
}