Construyendo una expresión OrderBy Lambda basada en la propiedad de la entidad hijo

c# expression-trees lambda linq

Pregunta

Estoy tratando de generar una cláusula LINQ OrderBy usando expresiones lambda con una entrada del nombre de columna de una entidad como una cadena (en la variable "sortOn" a continuación).

El siguiente código funciona bien para un valor de sortOn como "Código" que genera la lambda

p => p.Code

Pero también me gustaría clasificar en una entidad hijo, donde la lambda podría ser

p => p.Category.Description

Así que en este caso, me gustaría establecer sortOn = "Category.Description" y generar la expresión lamdba correcta.

es posible? Cualquier sugerencia sobre la mejor manera de hacer esto sería bienvenida.

Este código funciona bien para el caso simple:

var param = Expression.Parameter(typeof (Product), "p");

var sortExpression = Expression.Lambda<Func<Product, object>>(
    Expression.Property(param, sortOn), param);

if (sortAscending ?? true)
{
   products = products.OrderBy(sortExpression);
}
else
{
   products = products.OrderByDescending(sortExpression);
}

El caso de uso para este problema es mostrar una cuadrícula de datos y poder ordenar los datos, simplemente al pasar el nombre de la columna que se ordenará al servidor. Me gustaría hacer que la solución sea genérica, pero he comenzado a usar un tipo en particular (Producto en el ejemplo) por ahora.

Respuesta aceptada

Esto generará la expresión lambda adecuada:

var sortOn = "Category.Description";
var param = Expression.Parameter(typeof(Product), "p");
var parts = sortOn.Split('.');

Expression parent = param;

foreach (var part in parts)
{
    parent = Expression.Property(parent, part);
}

var sortExpression = Expression.Lambda<Func<Product, object>>(parent, param);

Respuesta popular

Puede usar la biblioteca dinámica de consultas LINQ para hacer esto fácilmente. Suponiendo que tenga una implementación de IQueryable<T> del Product , puede hacer fácilmente:

IQueryable<Product> products = ...;

// Order by dynamically.
products = products.OrderBy("Category.Description");

La publicación del blog tiene un enlace a la biblioteca y tendrá que crear / incluir el proyecto en su solución, pero funciona muy bien, y el análisis es muy sólido. Le impide tener que escribir el código de análisis usted mismo; incluso para algo tan simple, si los requisitos se expanden, la biblioteca lo tiene cubierto, mientras que una solución propia no lo hace.

También tiene una serie de otros operadores dinámicos ( Select , Where , etc.) para que pueda realizar otras operaciones dinámicas.

No hay magia debajo del capó, simplemente analiza las cadenas que se le pasan y luego crea las expresiones lambda basadas en los resultados del análisis.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow