1

申請書を書いています。ロギングには NLog を使用します。このアプリケーションでは、ほぼすべてのオブジェクトがログに書き込むことができます。そのための保護されたメンバーを定義します。

protected Logger logger;

protected virtual Logger Logger
{
     get { return logger ?? (logger = LogManager.GetLogger(this.GetType().ToString())); }
}

その場合、アプリケーションのすべての基本クラスに対してこのコードをコピーして貼り付ける必要があります。または、他のオプションが表示されます。ロガーを含むアプリ固有のルート オブジェクトを定義し、それをサブクラス化します。しかし、意味的には、これは間違っているように聞こえます。

より良いオプションはありますか?

4

2 に答える 2

7

ときどき、C# が複数の継承または mixin をサポートすることを本当に望みます....

拡張メソッドを書くことができます:

public static Logger Logger(this object obj) {
    return LogManager.GetLogger(obj.GetType());
}

欠点は、作成されたインスタンスがキャッシュされないため少し遅くなることです (実装の詳細である NLog の内部を除く) が、自分で行うことができます。

public static Logger Logger(this object obj) {
    Logger logger;
    Type type = obj.GetType();
    // s_loggers is static Dictionary<Type, Logger>
    if (!s_loggers.TryGetValue(type, out logger)) { // not in cache
        logger = LogManager.GetLogger(type);
        s_loggers[type] = logger;  // cache it
    }
    return logger;
}

次のように呼び出すことができます。

this.Logger.Log(...)

明らかな欠点は、任意のオブジェクトが他のオブジェクトのロガーに書き込むことができることです。

メモリリークに関するコメントについて(現在は削除されています):

最初の実装はそれを解決します。ただし、静的オブジェクトよりもリークではありません。これらのオブジェクトにアクセスできなければ、リークになります。別の方法として、ロガー自体の代わりにロガーにキャッシュすることもできますがWeakReference、NLog 自体に既にいくつかのキャッシュがあると思われるため、意味がありません。それ以外の場合、NLog は常にタイプごとに logger の新しいインスタンスを作成する必要があります。

于 2013-03-13T08:42:56.450 に答える
2

クラスごとのロガーを取得できるように、静的ロガーを使用することをお勧めします。これにより、インスタンスごとにロガーを作成するオーバーヘッドが停止します(ロガーはスレッドセーフです)。

class MyClass
{
    static readonly Logger logger = LogManager.GetCurrentClassLogger();
}

GetCurrentClassLoggerを使用すると、ロガーに明示的に名前を付ける必要がなくなりますが、実行時にスタックトレースからロガーの名前を把握する必要があるため、追加のオーバーヘッドが発生します。

ほとんどの場合、これは大したことではないでしょうが、そうでない場合は、これを行う方が少し速くなります。

class MyClass
{
    static readonly Logger logger = LogManager.GetLogger("MyClass");
}

わずかなオーバーヘッドがソリューションの問題であることが判明しない限り、/までGetCurrentClassLoggerを使用し続けます。

私が得ている印象は、タイピングを削減しようとしている、および/または重複コードをコピーして貼り付けることへの(良い)自然な嫌悪感に対処しているということです。

ただし、静的初期化子を使用してクラスごとにロガーを使用するこのパターンは広く受け入れられており、ほとんどの場合に最適に機能します。それに固執し、タイピングを節約するためにコードスニペットを設定するのが最善の方法かもしれません。

それでも満足できない場合は、依存性注入(コンストラクターまたはプロパティ注入のいずれかによる)またはアスペクト指向のログ管理でさえ、調査する必要がある他のことかもしれません。

于 2013-03-13T17:54:24.093 に答える