2015-02-02 3 views
1

Я создал сканер USB-устройств, который позволяет пользователю видеть все устройства в иерархии деревьев. Сначала я был счастлив, что это сработало, но после радости я увидел, что мое качество кода было ... не хорошо (см. Пример кода).C# Метод рекурсии для создания иерархии деревьев

Для лучшего понимания: Так выглядит дерево и что возвращает код.

BUS-Type    Device Description 
----------   ------------------- 
---------- 
PCI  |   |USB-Controller 
USB  |   |----|USB-Root Hub 
USB  |   |----|-----|Generic USB Hub 
USB  |   |----|-----|-----|USB Device 
USB  |   |----|-----|Generic USB Hub 
.      . 
.      . 
And so on. 

Теперь пример кода:

if (hierarchyDeviceZero.Children.Count != 0) { 
    for (int usbHierarchyLevelOne = 0; usbHierarchyLevelOne < hierarchyDeviceZero.Children.Count; usbHierarchyLevelOne++) { 
     foreach (var hierarchyDeviceOne in usbDeviceTree.USBDeviceNodes.Where(
      d1 => d1.HardwareID.Equals(hierarchyDeviceZero.Children[usbHierarchyLevelOne].HardwareID)) 
     ) { 
      Console.WriteLine("{0}\t|\t\t|---|{1}", hierarchyDeviceOne.EnumeratorName, hierarchyDeviceOne.Description); 
      if (hierarchyDeviceOne.Children.Count != 0) { 
       for (int usbHierarchyLevelTwo = 0; usbHierarchyLevelTwo < hierarchyDeviceZero.Children.Count; usbHierarchyLevelTwo++) { 
        foreach (var hierarchyDeviceTwo in usbDeviceTree.USBDeviceNodes.Where(
         d1 => d1.HardwareID.Equals(hierarchyDeviceOne.Children[usbHierarchyLevelTwo].HardwareID)) 
        ) { 
         Console.WriteLine("{0}\t|\t\t |---|{1}", hierarchyDeviceTwo.EnumeratorName, hierarchyDeviceTwo.Description); 
         if (hierarchyDeviceTwo.Children.Count != 0) { 
          for (int usbHierarchyLevelThree = 0; usbHierarchyLevelThree < hierarchyDeviceZero.Children.Count; usbHierarchyLevelThree++) { 
           foreach (var hierarchyDeviceThree in usbDeviceTree.USBDeviceNodes.Where(
            d1 => d1.HardwareID.Equals(hierarchyDeviceTwo.Children[usbHierarchyLevelThree].HardwareID)) 
           ) { 
. 
. 
. 
. 
And so on (until 10th Hierarchylevel). 

Мой вопрос, как я могу поставить это в метод рекурсивных? Я пробовал некоторые учебные пособия, но я несколько не понимал, как метод может называть себя 10 раз, не перезаписывая его значения ... Надеюсь, вы, ребята, понимаете, что я пытаюсь сделать так.

PS .: Извините за мой плохой английский.

+4

может быть лучше здесь: codereview.stackexchange.com –

+2

реорганизовать его к способу, который можно назвать с paremeter 'level' – DrKoch

+4

Переменные, объявленные в рамках метода (и параметров) являются локальными для * The конкретный вызов * этого метода. Таким образом, рекурсивный вызов использует отдельный набор локальных переменных. –

ответ

1

В вашей структуре данных я вижу нечто странное, а именно, у вас есть UsbDeviceTree со всеми узлами, но у вас также есть свойство .Children на отдельном узле.

Это, я думаю, вы можете сделать что-то подобное, если вы можете просто использовать узел .Children.

public class Device { 
    public int HardwareId { get; set; } 
    public Device[] Children {get; set; } 
    /* ...the rest... */ 
}        

void DisplayNodes(IEnumerable<Device> currentCollection, int indentation) { 
    foreach (var currentNode in currentCollection) { 
     // Display current node 
     Console.WriteLine(
      ... 
      display the node and 
      use the indentation parameter to control the --- or ---|--- 
      ... 
     ); 

     if (currentNode.Children != null) { 
      DisplayNode(currentNode.Children, indentation + 1); 
     } 
    } 
} 

// Data 
IEnumerable<Device> allDevices = usbDeviceTree.USBDeviceNodes; 
IEnumerable<Device> rootDevices = allDevices 
    .Where(x => x.IsRootNode /* TODO */) 
    .ToArray(); 

// Display 
DisplayNodes(rootDevices, 1); 
+0

Большое спасибо. Это очень помогло мне! Об этой структуре, я тоже работаю над этим =). – Megajin

Смежные вопросы