2017-10-13 4 views
1

Je voudrais créer une méthode d'extension comme linq pour obtenir tous les éléments d'une structure hiérarchique comme un arbre.Utiliser des génériques imbriqués sans beaucoup de code

ceci est mon extension

public static List<T> GetAllRecursive<T, TU>(this IList<T> list, Func<T, TU> func) where TU : IEnumerable<T> { 
     var allList = new List<T>(); 
     var toAdd = list.ToList(); 
     while(true) { 
      allList.AddRange(toAdd); 
      var childs = toAdd.SelectMany(x => func(x)).ToList(); 
      if(childs.Count == 0) { 
       return allList; 
      } 
      toAdd = childs; 
     } 
    } 

Je l'appelle comme ça

var allGuidelines = Guidelines.GetAllRecursive(x => (IEnumerable<MachineGuidelineTreeItemViewModel>)x.Children);

Comment puis-je améliorer cette Methode donc je ne ai pas besoin de jeter chaque fois que je l'utiliser?

Merci à l'avance

+0

Quel est le type de retour des enfants? –

+0

et pourquoi avez-vous besoin de le convertir en IEnumerable? X.Children n'est-il pas déjà IEnumerable <>? Est-ce un type plus générique, par exemple, IEnumerable ou quelque chose comme ça? Si oui, comment savez-vous que vous pouvez le convertir en IE ? – quetzalcoatl

+0

Children est un BindableCollection horotab

Répondre

1

Vous pouvez supprimer le paramètre de type TU et utilisez OfType sur IEnumerable à la place:

public static List<T> GetAllRecursive<T>(this IList<T> list, Func<T, IEnumerable> func) { 
    var allList = new List<T>(); 
    var toAdd = list.ToList(); 
    while(true) { 
     allList.AddRange(toAdd); 
     var childs = toAdd.SelectMany(x => func(x).OfType<T>()).ToList(); 
     if(childs.Count == 0) { 
      return allList; 
     } 
     toAdd = childs; 
    } 
} 

Cette approche est plus clémente, car il vous permet de passer des fonctions qui renvoient un sac mixte d'éléments, avec la méthode en le filtrant par type.

+0

Je pense que peut-être la variable 'toAdd' et la variable' childs', bien que requises, ne doivent pas nécessairement être 'List's. Probablement ne fera pas beaucoup de différence, mais je pense qu'il est possible d'éviter que 'ToList()' appel lors de l'attribution de 'childs' ... – BurnsBA

+1

@BurnsBA Je suis d'accord, il y a certainement de la place pour rendre cette méthode encore plus général. Je suis allé avec la mise en œuvre du PO pour remédier à une lacune spécifique, tout en gardant le reste de son code en place. – dasblinkenlight

+0

c'est exactement ce que je cherchais maintenant j'ai un petit appel: 'var allGuidelines = Guidelines.GetAllRecursive (x => x.Children);' - Merci – horotab