私は log4net でいくつかの奇妙な動作に遭遇し、誰かが私にこれを説明できるかどうか疑問に思いました。それを理解するためにもっと学びたいです。
私の WPF App.xaml.cs OnStartup オーバーライド メソッド内には、ログに使用される log4net プロパティを設定する次のコードがあります。
// logLocation is a path to a subdir in the users' appdata roaming dir
log4net.GlobalContext.Properties["LogLocation"] = logLocation;
logger = LogManager.GetLogger(typeof(App));
logger.Info("OnStartup: " + string.Join(" ", e.Args));
他のロガーを作成する前にこれを行います (またはそう思った)。
私の設定ファイルには、次の行があります。
<file type="log4net.Util.PatternString" value="%property{LogLocation}" />
これは、ログ ファイルの場所を指定するために機能します。ただし、これが失敗する状況に遭遇しました。その結果、実行ディレクトリのファイル名「(null)」への書き込みがログに記録されます。
これを引き起こしていると思われるのは、上記のコードの後の同じ OnStartup メソッドにある次の疑似コードです。
AnyClass ac = new AnyClass();
ac.NoOp();
AnyClass には、次のようにインスタンス化されたロガーがあります。
private static ILog logger = LogManager.GetLogger(typeof(AnyClass));
疑似コードを使用している理由は、インスタンス化してメソッドを呼び出す任意のクラスでこの動作を複製できるためです。メソッドが呼び出されない場合、ロギング パスは期待どおりに機能します。
注意すべき点がいくつかあります。
- これは、デバッガーでデバッグ モードまたはリリース モードで実行すると機能します。エラーは、exe を直接実行するか、「デバッグなしで開始」を介して実行した場合にのみ表示されます。
- ロガーが静的に定義されていない場合 - 問題は解決します
静的コンストラクターを AnyClass に追加すると、問題はなくなります。つまり、次のようになります。
静的 AnyClass() {}
ac.NoOp() への呼び出しを OnStartup によって呼び出されるセカンダリ メソッドに移動すると、エラーはなくなります。
要約すると、エラーは、静的ロガーの初期化を使用してクラスをインスタンス化し、OnStartup メソッド内でそのクラスのメソッドを呼び出すことによってのみ発生します。
これを回避するにはいくつかの方法がありますが、なぜこれが起こっているのかを理解するためにもっと学びたいです。