2009-12-10 10 views
1

J'ai une entité qui est en fait la structure de l'objet arbre (définir uniquement les propriétés pertinentes dans mon entité):Comment convertir des objets avec des objets imbriqués

public class TreeItem 
{ 

    public int Id { get; set; } 

    public TreeItem Parent { get; set; } 

    public List<TreeItem> Children { get; set; } 

    ... 

} 

Parent et les propriétés enfants sont correctement définies comme propriétés de navigation. Donc, quand je l'appelle quelque chose comme:

var items = (from ti in context.TreeItem() 
      select ti).ToList<TreeItem>(); 

Je reçois effectivement mes articles dans une structure arborescente, car EF sa magie derrière le rideau et mes parents et remplit les enfants sur ces articles.

Ce que je voudrais faire maintenant est de convertir ces objets en mes objets ViewModel qui sont beaucoup POCO. Pas de fonctionnalité, juste des données.

Je pourrais les convertir en ayant une méthode récursive qui créerait et peuplerait de nouveaux objets, mais y a-t-il un moyen plus simple (en termes de lignes de code de LoC) de faire ce genre de conversion?

+0

Je pense que vous pouvez construire un objet (une mesure) tout en faisant cette requête en utilisant expressions linq et lambda. Merci –

+0

Pas de problème, juste essayer d'aider. –

Répondre

1

En this question connexe plusieurs approches sont discutées:

  • L'récursive, sera probablement le plus facile à mettre en œuvre, mais en termes de mise à l'échelle de la profondeur et le nombre d'articles, elle est limitée car elle tend à de façon exponentielle prendre plus de temps et les risques débordant votre pile
  • une autre approche serait d'utiliser une pile qui, en termes de mise à l'échelle est beaucoup plus croissance linéaire

Assurez-vous de vérifier la com de Eric Lippert ment au bas de la page. Mise à jour

, pour vous donner une idée de ce que je veux dire:

public static class Extensions 
{ 
    public static IList<R> TransformTree<T, R>(this IEnumerable<T> collection, 
     Func<T, IEnumerable<T>> entitySelector, 
     Func<R, IList<R>> pocoSelector, 
     Func<T, R> transformer) 
    { 
     var transformedList = new List<R>(); 
     var stack = new Stack<IEnumerable<T>>(); 
     var parents = new Dictionary<IEnumerable<T>, R>(); 

     stack.Push(collection); 

     while (stack.Count > 0) 
     { 
      IEnumerable<T> items = stack.Pop(); 

      R transformedParent; 

      IList<R> parentChildren = parents.TryGetValue(items, out transformedParent) 
              ? pocoSelector(transformedParent) 
              : transformedList; 

      foreach (var item in items) 
      { 
       R transformedItem = transformer(item); 
       parentChildren.Add(transformedItem); 

       IEnumerable<T> children = entitySelector(item); 

       stack.Push(children); 
       parents.Add(children, transformedItem); 
      } 
     } 

     return transformedList; 
    } 
} 

appel comme si:

treeItems.TransformTree<TreeItem, TreeItemPoco>(
    (item) => { return item.Children; }, 
    (pocoItem) => { return pocoItem.Children; }, 
    (item) => { return new TreeItemPoco(item); }); 
+0

L'approche de la pile semble être beaucoup plus rapide que la récursivité, mais elle nécessite encore beaucoup de lignes. Je cherchais un truc simple sous la forme d'une série d'appels de méthode d'extension et/ou de lambdas ... mais j'utiliserai des piles si rien d'autre ne se présente. –

+0

Mais en y regardant de plus près, l'approche de la pile aplatit une structure arborescente en IEnumerable . Je veux convertir une structure arborescente en une structure arborescente différente, ce qui ne m'aide pas vraiment. –

+0

Je suis au courant; Gardez à l'esprit que vous voulez seulement marcher avec l'arbre et faire quelque chose avec. Qu'il s'agisse d'aplatir ou de recréer une arborescence avec des POCO. Les deux approches devraient toujours fonctionner. –

Questions connexes