log4net-Argument für LogManager.GetLogger

98

Warum erhalten die meisten log4net-Beispiele den Logger für eine Klasse auf folgende Weise:

private static ILog logger = 
    LogManager.GetLogger(
    System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

Anstatt nur typeof (MyClass) zu übergeben:

private static ILog logger = LogManager.GetLogger(typeof(MyClass));

Gibt es einen anderen Grund dafür als die Tatsache, dass Sie für die erste Option keinen bestimmten Klassennamen eingeben müssen?

Andy White
quelle

Antworten:

93

Ich denke du hast den Grund. Ich mache das so, damit ich mich nicht um den Klassennamen kümmern muss und einfach den Kesselplattencode kopieren und in eine neue Klasse einfügen kann.

Die offizielle Antwort finden Sie unter: Wie erhalte ich den vollständig qualifizierten Namen einer Klasse in einem statischen Block? an der log4net faq

Steven Lyons
quelle
Ok, das klärt es auf, danke für diesen Link, das hatte ich noch nie gesehen
Andy White
Dies ist so alt wie es nur geht, aber schauen Sie sich meine Antwort an, falls Sie diese noch als Kesselcode einfügen :)
Noctis
Sie sparen ein wenig Entwicklungszeit beim Ausschneiden und Einfügen dieses Codes. Das Aufrufen von 'GetCurrentMethod ()' ist jedoch mit Kosten verbunden, anstatt eine Zeichenfolgenkonstante zu verwenden oder 'typeof ()' aufzurufen. Wenn Sie addieren, wie oft dies über die Lebensdauer des Codes aufgerufen wird, und wie lange Sie brauchen, um den Klassennamen einzugeben, verlangsamen Sie Ihren Code meiner Meinung nach nur, um einen geringen Nutzen zu erzielen.
Youngs
1
Sie werden nicht so langsam, wie Sie denken. Dies ist ein statischer Aufruf. Sie haben also einen Aufruf pro Klasse und App-Domäne. Wenn Sie beispielsweise 300 Klassen haben, haben Sie höchstens 300 Aufrufe für die Lebensdauer Ihrer App
Paul Hatcher
Es macht keinen Sinn, Reflektion zu verwenden, um den Typnamen zu erhalten, und die Kopie / Vergangenheit ist Faulheit, und Sie erhalten einen Performance-Hit. Warum also nicht nur den Namen?!
MeTitus
8

Ich bin ein NLog-Benutzer und normalerweise läuft dies auf Folgendes hinaus:

var _logger = LogManager.GetCurrentClassLogger();

Es schien ein bisschen seltsam, dass Sie die Reflexion in Log4Net durchlaufen müssen, also habe ich mir den NLog-Quellcode angesehen, und siehe da, das tun sie für Sie:

[MethodImpl(MethodImplOptions.NoInlining)]
public static Logger GetCurrentClassLogger()
{
    string loggerName;
    Type declaringType;
    int framesToSkip = 1;
    do
    {
#if SILVERLIGHT
        StackFrame frame = new StackTrace().GetFrame(framesToSkip);
#else
        StackFrame frame = new StackFrame(framesToSkip, false);
#endif
        var method = frame.GetMethod();
        declaringType = method.DeclaringType;
        if (declaringType == null)
        {
            loggerName = method.Name;
            break;
        }
        framesToSkip++;
        loggerName = declaringType.FullName;
    } while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase));
    return globalFactory.GetLogger(loggerName);
}

Ich denke, ich würde etwas Ähnliches für Log4Net als Erweiterung oder statische Methode schreiben, anstatt die Reflexion als Teil meines Boiler-Codes einzufügen :)

Noctis
quelle
7

Wie Sie sagen - es ist praktisch, da Sie einen Logger in einer Methode erstellen können, ohne den Namen der Klasse zu kennen (trivial, wie ich weiß), aber Sie können Methoden zwischen Klassen ausschneiden und einfügen, ohne den Aufruf umbenennen zu müssen.

Preet Sangha
quelle
3

Ich denke, der Grund ist, dass Sie den Typ des Laufzeit-Typs mit der .DeclaringType()Methode erhalten. Sie können den Logger in einer Basisklasse verwenden und trotzdem den tatsächlichen Typ Ihres Objekts in der Logger-Ausgabe sehen. Das macht Untersuchungen viel bequemer.

PeterB
quelle
0

Es erleichtert auch das Erstellen von Codesmith-Vorlagen für die Codegenerierung.

Phillip H. Blanton
quelle