2013-11-08 3 views
0
говорят

Давайте у меня есть два класса:C# получить уровень вложенности дерева

public Foo 
{ 
    public List<Foo> Childs { get; set; } 
    public Bar BarObj { get; set; } 
    public int Level { get; set; } 
} 

public Bar 
{ 
    public List<Foo> Childs { get; set; } 
} 

Теперь я хочу, чтобы получить вложенности уровня из коллекции «Foo» Объекты

мой текущий метод работы выглядит следующим образом:

int currentLevel = 0; 
public void ApplyNestingLevel(List<Foo> list) 
{ 
    foreach(var item in list) 
    { 
     item.Level = currentLevel; 
     if(item.Childs.Count > 0 || item.BarObj.Childs.Count > 0) 
     { 
      currentLevel++; 
     } 
     ApplyNestingLevel(item.Childs); 
     ApplyNestingLevel(item.BarObj.Childs); 
    } 
} 

Как я могу сделать это более «элегантным/простым»?

+1

Может быть, вы могли прочитать о посетителя шаблон http://en.wikipedia.org/wiki/Visitor_pattern – wudzik

+1

я не вижу свойство «Else» в Foo. – Clinton

+0

oops sorry my bad ... typo – makim

ответ

3

Сохраните ссылку на родителя и сделайте рекурсивность уровня.

Я добавил пример и пару других предложений по дизайну в примере кода ниже. Надеюсь это поможет. FYI, это в значительной степени прямо из дизайна Gang of Four для Composite Pattern, что должно быть необходимо для чтения для любого, кто серьезно относится к ООП.

  • DoFactory .NET Composite Pattern
  • Design Patterns: Elements of Reusable Object-Oriented Software, on Amazon.com

    public class Foo 
        { 
    
         public Foo(Foo parent = default(Foo)) 
         { 
          this.parent = parent; 
          this.children = new List<Foo>(); 
         } 
    
         private readonly Foo parent; 
         private readonly List<Foo> children; 
    
         public int Level { get { return ReferenceEquals(parent,null) ? 0 : parent.Level + 1; } } 
    
         // don't expose the actual list... see below for why 
         public IEnumerable<Foo> Children { get { foreach(Foo child in this.children) yield return child; } } 
    
         // instead of exposing the child object list 
         // declare an explicit method with any parameters 
         // necessary. this allows you to enforce the invariant 
         // condition that all objects in a children collection 
         // will have their parent reference set to their 
         // actual parent 
         public void AddChild() 
         { 
          Foo newChild = new Foo(parent:this); 
          this.children.Add(newChild); 
         } 
    
         // if you need the ability to remove items as well, 
         // you can expose a remove method too. Just make 
         // sure that you validate expected preconditions 
         public int RemoveChild(Foo childToRemove) 
         { 
          if(ReferenceEquals(childToRemove,null)) throw new ArgumentNullException("childToRemove"); 
          if(!ReferenceEquals(this,childToRemove.parent)) throw new ArgumentException("The object cannot be removed because the current object is not the correct parent.","childToRemove"); 
          return children.RemoveAll((Foo existentChild) => existentChild.Equals(childToRemove)); 
         } 
    
    
        } 
    
3
public void ApplyNestingLevel(Foo f) 
{ 
    ApplyNestingLevel(f, 0); 
} 


public void ApplyNestingLevel(Foo f, int level) 
{ 
    if(f == null) { return; } 
    f.Level = level 
    if(f.Childs != null) { 
     foreach(Foo child in f.Childs) 
     { 
      ApplyNestingLevel(child, level + 1); 
     } 
    } 
    if(f.BarObj != null && f.BarObj.Childs != null) { 
     foreach(Foo child in f.BarObj.Childs) 
     { 
      ApplyNestingLevel(child, level + 1); 
     } 
    } 
} 
Смежные вопросы