2009-09-10 12 views
5

vi la siguiente función en un mensaje, que le permite a uno orden de los datos usando una expresión genérica:problema con la función genérica LINQ OrdenarPor

public static IOrderedQueryable<T> OrderBy<T, TKey>(
    this IQueryable<T> source, Expression<Func<T, TKey>> func, bool isDescending) { 
    return isDescending ? source.OrderByDescending(func) : source.OrderBy(func); 
} 

Cuando trato de utilizar esta función me sale un error que dice "El tipo o el nombre de espacio de nombres "TKey' no se pudo encontrar (¿falta una directiva using o una referencia de ensamblado?)" estoy haciendo algo tonto aquí, pero no puede averiguarlo

Editar:..

Después de investigar un poco más, creo que mi problema está en construir el Expr Ession que paso en ella. ¿Es posible construir una expresión que puede contener diferentes tipos? Digamos que mi conjunto de datos tiene una cadena, un int y un bool y quiero usar la función genérica anterior para ordenar por cualquiera de los elementos. ¿Cómo hago esto?

Tengo esta trabajando ahora:

if (IsString) 
{ 
    Expression<Func<T, string>> expString = ...; 
    // call orderBy with expString 
} 
else if (IsInt) 
{ 
    Expression<Func<T, int>> expInt; 
    // call orderBy w/ expInt 
} 
: 

Quiero algo como:

Expression<Func<T, {something generic!}>> exp; 
if (IsString) 
    exp = ...; 
else if (IsInt) 
    exp = ...; 
: 
// call orderBy with exp 
+0

Esto parece estar bien. ¿Cómo estás usando este método? ¿Lo agregaste a una clase estática? – BFree

Respuesta

2

Mi objetivo en esto era eliminar una gran cantidad de código repetitivo. Además de manejar el ascendente/descendente, mi función "OrderBy" maneja bien algunas otras lógicas comunes. Suponiendo que la definición de la función en la publicación original, uno puede simplemente hacer esto:

if ({need to sort by integer}) 
    query = OrderBy(objectT, a => a.myIntegerField, asc); 
else if ({need to sort by string}) 
    query = OrderBy(objectT, a=> a.myStringField, asc); 
: 
1

La expresión sólo puede tener un tipo; mi respuesta preferido aquí sería algo así como:

IQueryable<T> query = ... 
if({case 1}) { 
    query = query.OrderBy(x=>x.SomeValue); 
} else if({case 2}) { 
    query = query.OrderBy(x=>x.SomeOtherValue); 
} ... 

Sin embargo, si usted quiere hacer algo más flexible, lo que probablemente necesita para entrar en la costumbre Expression escrito; algo more like this.

+0

Eso es lo que originalmente tenía, pero terminé con una tonelada de código "duplicado" debido al hecho de que tengo muchos campos y necesito manejar géneros ascendentes/descendentes. La respuesta que publiqué parece estar funcionando bien. – ejwipp

4

Una observación rápida: En realidad, no es necesario utilizar una expresión lambda (Expression<Func<T,TKey>>). Un simple delegado (Func<T,TKey>) está bien.

Dicho esto, creo que la respuesta es posible que se busca es la siguiente:

Func<T,IComparable> func = null; 
if (IsString) 
    func = (T a) => a.SomeStringValue; 
else if (IsInt) 
    func = (T a) => a.SomeIntValue; 
// call orderBy with exp 
+0

Esto parece lo que estaba buscando. Sin embargo, jugué un poco con eso y no pude hacer que compilara. Cuando intento pasar func a una función OrderBy el compilador se queja. Su método sería un poco más limpio si funcionara, pero desafortunadamente no puedo dedicarle más tiempo en este momento. – ejwipp

+1

Cuando tenga tiempo, dígame cuál es el error del compilador que está viendo. – jpbochi

+0

Finalmente he vuelto a esto. Creo que el problema es que en mi función personalizada orderBy, realizo una llamada a ThenBy que no toma un argumento Func; requiere la expresión lambda. – ejwipp

0

Tome un vistazo a this answer

Mi manipulador genérico para la clasificación es:

  • "dgvProcessList" es mi dataGridView
  • "Proceso" es mi objeto enganchan a ella
  • "e" es mis DataGridViewCellMouseEventArgs

      PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First(); 
         if (isSortedASC == true) 
          dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderByDescending(x => column.GetValue(x, null)).ToList(); 
         else 
          dgvProcessList.DataSource = ((List<Process>)dgvProcessList.DataSource).OrderBy(x => column.GetValue(x, null)).ToList(); 
    
         isSortedASC = !isSortedASC; 
         dgvProcessList.ClearSelection(); 
    

Cheers

Cuestiones relacionadas