0

編集: 似ていますが、これは NLog ラッパーの使用に関する質問と同じではありません。拡張メソッドは別のレベルの間接化を追加し、適切なラッパーでさえ間違った呼び出しサイトを報告します

私は現在、NLog のロギング ラッパーを使用しており、正確なコールサイト情報を取得するために、ソースの例に示されているトリックを使用しています。私が開始した新しいプロジェクトでは、より単純なクラスを作成したかったので、次のようなインターフェイスを実装しました。

public interface ILogger
{
    void Log( LogEntry entry );
}

そして、次のような拡張メソッド クラスを作成しました。

public static class LoggerExtensions
{
    public static void Debug( this ILogger logger, string format, params object[] args)
    {
        logger.Log( new LogEntry( LogLevel.Debug, format, args ) );
    }

    ...
}

問題は、NLog が呼び出しサイトを拡張メソッドの呼び出し元ではなく拡張メソッドとして表示することです。少し調べてみましたが、NLog と拡張メソッドについては何も見つかりませんでした。

この場合、callsite 情報を修正することは可能ですか? または、インターフェイス自体にデバッグ、情報などの機能を含める唯一の方法はありますか?

4

3 に答える 3

8

パーティーに遅れましたが、ラッパーに拡張メソッドを使用しているため、このソリューションに問題がありました。アセンブリを LogManager に渡すことで、NLog に拡張クラスを無視させることができました。

    /// <summary>
    /// Bootstrap the wrapper class
    /// </summary>
    static Logger()
    {
        LogManager.AddHiddenAssembly(typeof(LoggingExtensions).Assembly);
    }

ドキュメント以外の詳細はあまりありません

NLog がスタック トレースで呼び出し元のメソッドを見つけようとしているときにスキップされる特定のアセンブリを追加します。

NLogドキュメントから

この設定により、拡張メソッド + DI を SimpleInjector で動作させることさえできました。

この方法を使用して、同じアセンブリ内に呼び出しサイトを引き続き持つことができることを示すために

私の Logger() は、SettingsHelper() と共に Utilities プロジェクトに存在します。SettingsHelper からの出力を使用してテストをセットアップします。

2015-08-18 20:44:07.5352 | vstest.実行エンジン.x86 | デバッグ | Utilities.Settings.SettingsHelper | Logger() と同じアセンブリからのテスト | ActionTests.LoggingTest+LogTest.RunLogTest

太字は ${callsite} です

私の SettingsHelper() テスト:

ILogger logger = new Logger(typeof(SettingsHelper));
logger.Debug("A test from the same assembly as Logger()");

LogEventInfo() を取るオーバーロードを使用することも忘れないでください。

_logger.Log(typeof(Logger), logEvent);
于 2015-08-19T12:17:19.433 に答える
1

編集:残念ながら、この回答は機能しなくなりました。NLog は 3.2.0 でこの機能を壊しており、修正する予定はないようです: https://github.com/NLog/NLog/issues/696

回避策を見つけました。NLogラッパーのソリューションと同じではありませんが、似ていることがわかります。

ILogger の実装者 (NLog ラッパー) が独自の型を単に NLog に渡す代わりに、呼び出し元から型を渡すことができるオーバーロードを作成しました。

public void Log( LogEntry entry )
{
    this.Log( this.GetType(), entry );
}

public void Log( Type type, LogEntry entry)
{
    NLogLogger.Log( type, new NLog.LogEventInfo( ... ) );
}

これには、インターフェイスにオーバーロードを追加する必要があり、それは一種の醜いものになります (そして NLog 固有):

public interface ILogger
{
    void Log( LogEntry entry );
    void Log( Type type, LogEntry entry );
}

次に、拡張メソッドを変更できます。

public static class LoggerExtensions
{
    public static void Debug( this ILogger logger, string format params object[] args )
    {
        logger.Log( typeof(LoggerExtensions), LogLevel.Debug, format, args ) );
    }

    ...
}

単にラッパーを使用するほどきれいではありませんが、これにより、呼び出しサイト情報を保持しながら拡張メソッドを使用できます。誰かがよりきれいな方法を持っているなら、私はそれを見たいです。

于 2013-05-03T20:31:58.763 に答える
0

LogEntry は独自のクラス/構造体ですか? ロガータイプを保持するために、フィールド/プロパティを追加することができます。拡張メソッドで、ILogger に送信する LogEntry を作成するときに、LogEntry.LoggerType に typeof(LoggerExtensions) を入力します。

したがって、LoggerExtensions クラスは次のようになります (コンパイルもテストもされていません)。

public static class LoggerExtensions
{
    public static void Debug( this ILogger logger, string format, params object[] args)
    {
        logger.Log( new LogEntry( typeof(LoggerExtensions), LogLevel.Debug, format, args ) );
    }

    ...
}

log4net は同様のスキームを使用するため (ロガー タイプを調べて、実際の呼び出しサイトに対応するスタック フレームを特定する)、log4net ラッパーと対応する log4net ラッパー拡張メソッドを作成することもできます。

于 2013-05-06T17:15:34.353 に答える