2017-11-21 5 views
4

私はログメッセージのためにlog4netとlog4jの"format" APIを熱心に扱っています。これは、必要なログレベルが有効になっていない場合に引数にToString()を呼び出すコストを回避します。高価な引数を持つDebugFormat()を使用する方法はありますか?

しかし、使用する引数の1つ以上が単純なオブジェクトではない場合があります。何らかの方法で構築する必要がある場合があります。たとえば、次のように:DebugFormatはそれはのToStringメソッドの場合と同様に、それは(あるべきと判断した場合を除き

logger.DebugFormat("Item {0} not found in {1}", 
     itemID, 
     string.Join(",", items.Select(i => <you get the idea>)) 
     ); 

は、それが実行されないように(表現を参加)第二引数をカプセル化する技術があります最初の議論)?

ラムダやfuncのような感じがするかもしれませんが、何かがここで助けてくれるはずですが、私はC#をかなり新しくしています。

+2

それはこれが可能であるようには見えません - 私はあなたがそれのように見える 'のFunc '、 'Expression'などを取ることを可能にする過負荷を見つけることができませんこのシナリオでは、 'if(logger.IsDebugEnabled)'を使用してラップする方法が実際の唯一の選択肢かもしれません。 –

+0

あなたはlog4netまたはカスタムソリューションに何か組み込みを意味していますか? – Evk

+0

デリゲートを取る 'DebugFormat'のラッパーを書くのは簡単ですが、それはあなたが望むものですか? – DavidG

答えて

6

拡張メソッドまたはラッパークラスを作成できますが、いくつかのパラメータ(例ではitemID)を明示的に指定し、必要な場合にのみ解決する必要があるため、満足のいく構文を取得するのは簡単ではありません。しかし、無名関数をobjectとして渡すことはできません。代わりに、拡張メソッドやラッパーを必要としない別のソリューションを使用します。

public sealed class Delayed { 
    private readonly Lazy<object> _lazy; 
    public Delayed(Func<object> func) { 
     _lazy = new Lazy<object>(func, false); 
    } 

    public override string ToString() { 
     var result = _lazy.Value; 
     return result != null ? result.ToString() : ""; 
    } 
} 

これはコンストラクタでオブジェクトを返す関数を受け入れ、ToString()が呼び出されるまで、あなたは(そのようなデバッグレベルが有効になっている場合)にのみ、必要な場合にlog4netによって呼び出される知っているようにこれは、この関数を呼び出しません。このようなクラスを作成します。 。そして、このように使用します。

logger.DebugFormat("Item {0} not found in {1}", 
    itemID, 
    new Delayed(() => string.Join(",", items.Select(i => <you get the idea>))) 
    ); 
+0

これは実際にはかなりいいです。 Funcの配列をとる拡張メソッドを書くことに誘惑されましたが、これはトリックです。 – DavidG

+0

'_hasResolved'などを持っているのではなく、'遅延 'の内部に' Lazy 'を使うのはどうですか? –

+1

@ serpent5はいあなたは正しいです、更新されました。 – Evk

関連する問題