Select Join ricorsiva in c# con Linq

imagesOggi ho avuto bisogno di creare un extension method per poter selezionare in modo ricorsivo i figli di figli di un item padre in una lista.đŸ™‚

Ecco una soluzione pulita per fare gerarchica ricorsiva join in LINQ e C#. Ho avuto difficolta’ a trovare su internet un esempio, quindi ho deciso di scrivere un post con il mio approccio che fornisce metodi di estensione per IEnumerabe <T> per fare ricorsione:

Prima di tutto la mia struttura gerarchica:
Text | ID | Parent ID
A | 1 | –
B | 2 | –
C | 3 | 1
D | 4 | 1
E | 5 | 2

I dati sono rappresentati dall’oggetto

public class ObjectData
{
   public string Text { get; set; }
   public int Id { get; set; }
   public int ParentId { get; set; }
}

mentre i nodi gerarchici dal seguente oggetto:

public class NodeData
{
 public string Text { get; set; }
 public IEnumerable<NodeData> Children { get; set; }
}

Il nostro obiettivo e’ avere un oggetto gerarchico fatto in questo modo:
A –>
|_ C
|_ D
B —>
|_ E

Usando il mio metodo di estensione RecursiveJoin LINQ, è possibile trasformare i dati (rappresentati da ObjectData) in dati gerarchici (rappresentati da NodeData) come segue:

Prima di tutto creiamo i nostri dati:

ObjectData[] elements = new ObjectData[][]
{
   new ObjectData[]{Id = 1, Text = "A"},
   new ObjectData[]{Id = 2, Text = "B"},
   new ObjectData[]{Id = 3, ParentId = 1, Text = "C"},
   new ObjectData[]{Id = 4, ParentId = 1, Text = "D"},
   new ObjectData[]{Id = 5, ParentId = 2, Text = "E"}
};

E poi implementiamo il RecursiveJoin per creare il nostro oggetto “ricorsivo”

IEnumerable<NodeData> nodes = elements.RecursiveJoin(element => element.Id,
 element => element.ParentId,
 (ObjectData element, IEnumerable<NodeData> children) => new NodeData()
 {
 Text = element.Text,
 Children = children
 });

Ci saranno due root nodi A e B. A avra’ i figli C e D mentre B avra’ come figlio solo E.
L’esempio usa semplicemente la forma del metodo RecursiveJoin con la seguente firma:

public static IEnumerable<TResult> RecursiveJoin<TSource, TKey, TResult>
   (this IEnumerable<TSource> source,
      Func<TSource, TKey> parentKeySelector,
      Func<TSource, TKey> childKeySelector,
      Func<TSource, IEnumerable<TResult>, TResult> resultSelector);

Il codice della classe si puo’ trovare sul mio Github

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...