[C#] log4netで呼び出し元のクラス・メソッド名をスタックトレースから取得するのはダメでCallerMemberName属性を使うべき

ILog取得する時にいちいちメソッド名とか指定するのがメンドイじゃん?

スタックトレースからメソッド名持ってくればいいよね? これって問題ある?Flyweightになっててメモリ食うか?

1
2
3
4
5
6
7
8
9
10
11
// この方法はダメダメです。CallerMemberName属性を使いましょう!
private static ILog GetLogger()
{

MethodBase m = (new StackTrace(false)).GetFrame(2).GetMethod();
return LogManager.GetLogger(m.DeclaringType.Name + '.' + m.Name);
}

public static void InfoFormat(string format, params object[] args)
{

GetLogger().InfoFormat(format, args);
}

…で、その後、この方法はダメだったことが判明 ↓

StackFrameは使うな。CallerMemberName属性を使え。

上記のStackTraceを使う方法はいろいろとダメだった。 まずStackTraceではなくStackFrameを直接取得した方がいいという点。 場合によってはStackFrameが取得できないことがあるという点。

参考: C# メソッドの呼び出し元メソッド名を取得するおまじない - Qiita

なので、System.Runtime.CompilerServices.CallerMemberNameAttribute を使ってコンパイル時にメソッド名を埋め込んでもらうようにした方がいい。 これだと可変長引数が使えないけど…使えないからといってさほど不便ではないはず。

1
2
3
4
5
6
// CallerMemberName属性を付けると
// コンパイル時にメソッド名に置き換えてくれる
public void TraceDebug(string text, [CallerMemberName] string name = "")
{

log4net.LogManager.GetLogger(name).Debug(text);
}
関連があるかもしれない記事