2009-04-01 5 views
2

Ich entwickle gerade eine Anwendung, die den Namespace System.DirectoryServices verwendet, um ein DirectoryEntry-Objekt zu erstellen und die gesamte Hierarchie durchzuziehen, um Informationen zu sammeln.Looping durch DirectoryEntry oder eine beliebige Objekthierarchie - C#

Ich weiß nicht, Anzahl der untergeordneten Einträge für jedes Directory Objekt in der Hierarchie, so kann ich nicht eine Anzahl von N verschachtelten Schleifen Spinnen durch die Kinder Eigentum

Hier ist mein Pseudo-Code-Beispiel erstellen:

//root directory 
DirectoryEntry root = new DirectoryEntry(path); 

if(DirectoryEntry.Childern != null) 
{ 
    foreach(DirectoryEntry child in root.Children) 
    { 
     //loop through each Children property unitl I reach the last sub directory 
    } 
} 

Meine Frage ist, was ist der beste Weg, um eine Schleife zu erstellen, um Informationen zu sammeln, wenn Sie so nicht die Anzahl der Unterverzeichnisse in Ihrem Objekt wissen?

(Dies kann auf jede Art von Objekt angewendet werden, die Sie nicht die Objekthierarchie weiß)

Antwort

5

Verwenden Sie eine rekursive Funktion, wenn Sie die Tiefe der Hierarchie nicht kennen und alle Ebenen durchlaufen müssen. Unten finden Sie ein Beispiel für die Tiefen-Traversierung.

using (DirectoryEntry root = new DirectoryEntry(someDN)) 
{ 
    DoSomething(root); 
} 


function DoSomething(DirectoryEntry de) 
{ 
    // Do some work here against the directory entry 

    if (de.Children != null) 
    { 
     foreach (DirectoryEntry child in de.Children) 
     { 
      using (child) 
      { 
       DoSomething(child); 
      } 
     } 
    } 
} 

Alternativ ohne Rekursion können Sie eine Traversal tun, um eine Queue oder Stack-Datenstruktur durch Hinzufügen und Speichern der Objekte, die Sie gesehen haben, aber noch besucht haben.

Queue<DirectoryEntry> queue = new Queue<DirectoryEntry>(); 
DirectoryEntry root = new DirectoryEntry(someDN); 
queue.Add(root); 

while (queue.Any()) 
{ 
    using (DirectoryEntry de = queue.Dequeue()) 
    { 
     // Do some work here against the directory entry 

     if (de.Children != null) 
     { 
      foreach (DirectoryEntry child in de.Children) 
      { 
       queue.Enqueue(child); 
      } 
     } 
    } 
} 
+0

Dies, btw, ist ein gutes Beispiel dafür, wo Rekursion ist eigentlich ein guter Weg, um ein Problem zu behandeln. Da das Dateisystem selbst Tiefeneinschränkungen auferlegt, sollten Sie den Stapel nicht blasen. Sie müssen jedoch vorsichtig sein, falls es eine Schleife in der Baumstruktur zu Links gibt ... –

+0

@jeffmaphone: DirectoryEntry wird tatsächlich auf einen LDAP-Server zeigen, nicht auf das Dateisystem. Ich bin mir nicht sicher über die LDAP-Tiefengrenzen, aber wenn es Schleifen gibt, ist es am einfachsten, die GUID jedes von Ihnen besuchten Eintrags aufzuzeichnen und die Rekursion zu beenden, wenn Sie denselben Eintrag zweimal besuchen. –

+0

Verwenden Sie 'using (child) {...}' innerhalb der foreach-Schleife, um sicher zu sein, nach sich selbst zu bereinigen. siehe http://stackoverflow.com/questions/41378746/disposing-during-foreach/41378945#41378945 – Born2Smile

1

Sie eine Funktion verwenden können, die auf die Kinder nennt sich rekursiv. Ausgangsbedingung: keine weiteren Kinder usw.

1

Eine Option ist die Verwendung von Rekursion. Stellen Sie diesen Code in einer Funktion auf, die sich dann selbst in der foreach-Schleife aufruft und das nächste Verzeichnis (untergeordnetes Element) jedes Mal weiterleitet.

1

Willkommen in der wunderbaren Welt der Rekursion. Sie benötigen eine Funktion, die ein Verzeichnis als Argument akzeptiert. Wenn dieses Verzeichnis angegeben wird, sucht es alle untergeordneten Verzeichnisse und ruft für jedes ... sich selbst auf.

2

Sie haben als rekursive Funktion schreiben ...

DirectoryEntry root = new DirectoryEntry(path); 
DoForEveryNode(root); 

void DoForEveryNode(DirectoryEntry node) 
{ 
    // do something.. 

    foreach(DirectoryEntry child in node.Children) 
    { 
     DoForEveryNode(child); 
    } 
}