2010-10-06 7 views
6

Ho una funzione che attualmente prende tutte le cartelle e sottocartelle per controllare l'ACL di un piccolo strumento che sto costruendo, ma sto tirando fuori i miei capelli cercando di capire come limitare la profondità a cui può andare. Ad esempio hai una cartella che ha 4 livelli di profondità ma voglio essere in grado di prenderne solo 3 livelli per ACL.Come limitare la profondità di un ricorsivo sottodirectory Ricerca

Attualmente l'ho codificato questa convenzione:

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); 
    } 
} 

Ovviamente questo non è bello come è stato perché ho lavorato sul problema per un po ', ma se qualcuno mi può puntare nella giusta direzione per risolvere questo problema sarei molto felice!

+0

ciò che non funziona per voi? Sembra che questo codice non venga compilato - dove è recCount dichiarato (e pBar e Depth)? e il vostro (commentato) MessageBox.Show utilizza contatore invece .... –

risposta

18

In primo luogo, evitare di dichiarare il campo recCount esterno come una variabile “globale”. Negli scenari ricorsivi è solitamente più gestibile passare lo stato lungo le chiamate ricorsive.

In secondo luogo, spostare il test di profondità su foreach per rimuovere query non necessarie del file system per le sottodirectory.

In terzo luogo, inserire la logica di elaborazione effettiva all'inizio del tuo metodo, ancora una volta fuori dal giro di elaborazione sottodirectory.

Il tuo codice sarebbe quindi simile:

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

Mi hai appena salvato un mal di testa nel pomeriggio! Grazie! –

+0

E 'fantastico sentirlo, sono contento che la mia soluzione ti abbia aiutato. –

+3

Invece di passare il parametro CurrentDepth, la mia preferenza normale sarebbe passare a depthLimit, che conterrebbe il conto alla rovescia invece che verso l'alto. – supercat

5

Un possibile metodo, aggiungere un campo di classe di fuori del metodo e una variabile per indicare quanti livelli di profondità per andare max.

livelli INT;

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

In realtà, 'livelli non rappresenta la profondità, ma il numero di 'StepThroughDirectories' chiamate. – digEmAll

+1

Lo svantaggio di questo è che non è possibile avere due chiamate a StepThroughDirectories in corso contemporaneamente (poiché i livelli potrebbero essere condivisi). Forse non è un problema in questa applicazione, ma la soluzione di Ondrej Tucny è più autonoma e più pulita. –

+0

@Paul Buon punto. Non ci ho pensato mentre rispondevo. – jac

2

Decremento RECCOUNT quando si torna dal StepThroughDirectories, ma questo sarebbe meglio ...

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

Beh, sì, questa è la fonte dell'errore che non ho notato all'inizio. Tuttavia, il design è un po 'goffo, quindi alcuni refactoring per renderlo più leggibile e gestibile sarebbero anche di consulenza. –

+0

Modificato il mio post per aggiungere il refactoring proposto – Les

+0

Tutti i suggerimenti postati sembrano concordare sul fatto che passare lo stato verso il basso della ricorsione è una pratica raccomandata, una migliore coesione, un accoppiamento ridotto (a livello globale). – Les