2016-03-24 10 views
1

TL; DR - Sprung zum letzten AbsatzWie kann ich die Einrückung beim Ein-/Ausstieg aus Methoden erhöhen/verringern?

Hintergrund

ich einige Daten gesteuerte Tests durchführen und die Protokolldatei als eine der Testausgänge. Es funktioniert so etwas wie this-

  • in Ordner erste Datei lesen
    • Prozess erste Zeile und konvertieren zu einem Test
    • Run Test
      • Perform Validation 1
      • ...
    • ...
  • lesen nächste Datei
  • Etc.

Meine Log-Datei spiegelt dies:

INFO - Start RunAllFilesInFolder 
INFO - File1: 
INFO -  Some info 
INFO -  Executing Test 1 
INFO -   Validation A result 
INFO -   ... 
INFO -  ... 
INFO - File2: 
... 

Im Moment benutze ich/Call Log 4 Netz wie this-

static class LogHelper 
{ 
    internal static readonly log4net.ILog Log = log4net.LogManager.GetLogger 
      (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 
} 

// another file 
using static Some.Namespace.LogHelper; 
class SomeClass 
{ 
    Log.Info($"\t\tExecuting {t.Number}-{t.Name}"); 
} 

Wobei Einrückung = "\ t", "\ t \ t" oder "\ t \ t \ t" abhängig von der Ebene, in der sich der Test befindet.


Gibt es eine Möglichkeit, den Anruf zu LogHelper.Log Refactoring, so dass es berücksichtigt eine statische „indent“, die erhöht werden kann/verringert, wie ich in die verschiedenen Teststufen fort, ohne explizit den Einzug in die Angabe jeder Anruf?

I.e. einfach mit der Lage sein, gegebenenfalls etwas wie

Log.Indent.Increase(); 

Oder

Log.Indent.Decrease(); 

und ersetzen Sie den obigen Aufruf rufen anmelden -

Log.Info($"Executing {t.Number}-{t.Name}"); 

Antwort

1

Sie die Länge stack trace verwenden könnte, durch Zählen die Anzahl der neuen Zeilen:

int someSensibleMinimum = 3; //something that works for you 
int count = Environment.StackTrace.Count(a => a=='\n'); 
var indent = new string('\t', Math.Max(0, count - someSensibleMinimum)); 

Beachten Sie, dass anders in Release es verhalten:

Allerdings berichten die Eigenschaft Stacktrace ist vielleicht nicht so viele Methodenaufrufe als wegen Code-Transformationen erwartet, die bei der Optimierung auftreten.

Oder könnten Sie automatisch die Länge mit diesem Ansatz berechnen (Pseudo-Code):

int count = Environment.StackTrace.Count(a => a=='\n'); 
Look for stack length in dictionary<int,string> (length to indent string) 
If found use it. 
If not found, find the largest entry in dictionary where key < count 
add new entry to dictionary one tab char longer 

In Code:

public sealed class IndentTracker 
{ 
    private readonly ThreadLocal<Dictionary<int, string>> _dictionaryLocal = 
     new ThreadLocal<Dictionary<int, string>>(() => new Dictionary<int, string>()); 

    public string GetIndent() 
    { 
     Dictionary<int, string> dictionary = _dictionaryLocal.Value; 

     int count = Environment.StackTrace.Count(a => a == '\n'); 

     if (!dictionary.Any()) 
     { 
      string initialIndent = string.Empty; 
      dictionary.Add(count, initialIndent); 
      return initialIndent; 
     } 

     string indent; 
     if (dictionary.TryGetValue(count, out indent)) 
      return indent; 

     string last = dictionary.OrderByDescending(k => k.Key).First(k => k.Key < count).Value; 
     string newIndent = last + '\t'; 
     dictionary.Add(count, newIndent); 
     return newIndent; 
    } 
} 

Dies funktioniert, wenn log in die Tiefe, um zu erhöhen. Zum Beispiel schlägt es fehl, wenn Sie bei Stapeltiefe 10 und dann 5 (ohne vorherige Protokollierung bei Stapeltiefe 5 dann 10) anmelden.

+0

Danke für die detaillierte Antwort! Leider kann es zu diesem Zeitpunkt für meine Zwecke zu viel Overkill sein ... Könnten Sie versuchen, die spezifische Frage (letzter Absatz) mit Ihrer IndentTracker-Klasse zu beantworten? –

+0

Ich habe die Frage bearbeitet, um klarer zu sein, was genau ich bin –

+0

Klingt sehr einfach jetzt. Nicht sicher, wo Sie Schwierigkeiten haben, das selbst zu implementieren. – weston