Costruire un'espressione OrderBy Lambda in base alla proprietà dell'entità figlio

c# expression-trees lambda linq

Domanda

Sto cercando di generare una clausola LINQ OrderBy usando espressioni lambda con un input del nome della colonna di un'entità come stringa (nella variabile "sortOn" sotto).

Il codice sotto funziona bene per un valore sortOn come "Codice" che genera il lambda

p => p.Code

Ma mi piacerebbe anche ordinare su un'entità bambino, dove potrebbe essere il lambda

p => p.Category.Description

Quindi, in questo caso, mi piacerebbe impostare sortOn = "Category.Description" e avere l'espressione corretta di lamdba generata.

È possibile? Qualsiasi suggerimento sul modo migliore per farlo sarebbe ben accetto.

Questo codice funziona bene per il caso semplice:

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);
}

Il caso d'uso per questo problema è la visualizzazione di una griglia di dati e la possibilità di ordinare i dati, semplicemente passando il nome della colonna da ordinare sul server. Mi piacerebbe rendere la soluzione generica, ma per ora ho iniziato a utilizzare un particolare tipo (Prodotto nell'esempio).

Risposta accettata

Questo genererà un'espressione lambda corretta:

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);

Risposta popolare

Puoi usare la libreria di query Dynamic LINQ per farlo facilmente. Supponendo che tu abbia un'implementazione IQueryable<T> di Product , puoi facilmente fare:

IQueryable<Product> products = ...;

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

Il post del blog ha un link alla libreria e dovrai costruire / includere il progetto nella tua soluzione da solo, ma funziona molto bene e l'analisi è molto solida. Ti impedisce di dover scrivere il codice di analisi da solo; anche per qualcosa di così semplice, se i requisiti si espandono, la biblioteca è coperta, mentre una soluzione homegrown no.

Ha anche una serie di altri operatori dinamici ( Select , Where , ecc.) In modo da poter eseguire altre operazioni dinamiche.

Non c'è magia sotto il cofano, esso solo analizza le stringhe che si passano e quindi crea le espressioni lambda in base ai risultati di analisi.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché