2010-10-06 5 views
6

Ich habe eine Funktion, die derzeit alle Ordner und Unterordner erfasst, um die ACLs für ein kleines Tool zu überprüfen, das ich baue, aber ich ziehe mir die Haare aus versuchen herauszufinden, wie man die Tiefe begrenzen kann, zu der es gehen kann. Zum Beispiel haben Sie einen Ordner, der 4 Ebenen tief geht, aber ich möchte in der Lage sein, nur 3 Ebenen davon für ACLs zu greifen.Wie man die Tiefe einer rekursiven Unterverzeichnis Suche eingrenzt

Zur Zeit habe ich es codiert thusly:

private void StepThroughDirectories(string dir) 
{ 
    string[] directories = Directory.GetDirectories(dir); 
    try 
    { 
     foreach (string d in Directory.GetDirectories(dir)) 
     { 
      if (recCount < (int)Depth) 
      { 
       GetACLs(d, new DirectoryInfo(d)); 
       pBar.Value += 1; 
       //MessageBox.Show("Recursive Level: " + counter.ToString()); 
       recCount++; 
       StepThroughDirectories(d); 
      } 
      else 
      { 
       recCount--; 
      } 
     } 
    } 
    catch (System.Exception e) 
    { 
     Console.WriteLine(e.Message); 
    } 
} 

Ganz offensichtlich ist das nicht so schön wie es war, weil ich habe das Problem für eine Weile arbeiten, aber wenn jemand kann mich in der richtigen Richtung zu löse dieses Problem Ich würde mich sehr freuen!

+0

Was ist für Sie nicht funktioniert? Sieht so aus, als würde dieser Code nicht kompiliert - wo ist recCount deklariert (und pBar und Depth)? und Ihre (auskommentierte) MessageBox.Show verwendet stattdessen den Zähler .... –

Antwort

18

Zuerst vermeiden erklärt die recCount Feld außerhalb als „global“ Variable. In rekursiven Szenarien ist es in der Regel einfacher, den Zustand entlang der rekursiven Aufrufe zu übergeben.

Zweitens verschieben Sie den Tiefentest aus dem foreach, um unnötige Abfragen des Dateisystems für Unterverzeichnisse zu entfernen.

Drittens, legen Sie die eigentliche Verarbeitungslogik am Anfang Ihrer Methode, wieder aus der Unterverzeichnisse Verarbeitungsschleife.

Ihr Code würde dann wie folgt aussehen:

void StepThroughDirectories(string dir) 
{ 
    StepThroughDirectories(dir, 0) 
} 

void StepThroughDirectories(string dir, int currentDepth) 
{ 
    // process 'dir' 
    ... 

    // process subdirectories 
    if (currentDepth < MaximumDepth) 
    { 
     foreach (string subdir in Directory.GetDirectories(dir)) 
      StepThroughDirectories(subdir, currentDepth + 1); 
    } 
} 
+0

Du hast mir gerade Kopfschmerzen am Nachmittag gerettet! Vielen Dank! –

+0

Schön das zu hören, ich bin froh, dass meine Lösung Ihnen geholfen hat. –

+3

Anstatt currentDepth zu übergeben, würde ich normalerweise depthLimit übergeben, das würde eher abwärts als aufwärts zählen. – supercat

5

Eine mögliche Methode, fügen Sie ein Klassenfeld außerhalb Ihrer Methode und eine Variable, um anzuzeigen, wie viele Ebenen tief zu gehen, max.

int Ebenen;

private void StepThroughDirectories(string dir, int depth) 
{ 
    levels ++; 
    if (levels > depth) 
     return; 
    string[] directories = Directory.GetDirectories(dir); 
    try 
    { ... 
+0

Tatsächlich repräsentiert "levels" nicht die Tiefe, sondern die Anzahl der 'StepThroughDirectories' Aufrufe. – digEmAll

+1

Der Nachteil davon ist, dass Sie nicht gleichzeitig zwei Aufrufe von StepThroughDirectories gleichzeitig ausführen können (da Ebenen geteilt werden müssen). Vielleicht kein Problem in dieser Anwendung, aber Ondrej Tucnys Lösung ist selbständiger und sauberer. –

+0

@Paul Guter Punkt. Daran habe ich nicht gedacht. – jac

2

Decrement RECCOUNT, wenn Sie von StepThroughDirectories zurück, aber dies wäre besser ...

private void StepThroughDirectories(string dir, int depth) 
    { 
     if (depth < 0) 
      return; 
     string[] directories = Directory.GetDirectories(dir); 
     try 
     { 
      foreach (string d in Directory.GetDirectories(dir)) 
      { 
       // your code here 
       Console.WriteLine("{0}", d); 
       StepThroughDirectories(d, depth-1); 
      } 
     } 
     catch (System.Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 
    } 
+0

Nun ja, das ist die Quelle des Fehlers, den ich zuerst nicht bemerkt habe. Allerdings ist das Design ein bisschen ungeschickt, so dass einige Refactoring, um es lesbarer und überschaubarer zu machen, auch beratend wäre. –

+0

Redigierte meinen Beitrag, um meinen vorgeschlagenen Refactor hinzuzufügen – Les

+0

Alle bisherigen Vorschläge scheinen darin übereinzustimmen, dass das Übergeben des Staates die Rekursion ist eine empfohlene Praxis, bessere Kohäsion, verringerte Kopplung (zu globals). – Les

Verwandte Themen