ログへの呼び出しの一部として、文字列の代わりにデリゲートを取る NLog の機能を利用しています。例えば
log.Error(()=>"I am an error which was encountered at " + DateTime.Now)
このデリゲートは、ロギングが有効になっている場合にのみ評価されます。理論的には、デリゲートが常に評価されるとは限らないため、より高速な実行が可能になります。気の利いた。
私の問題は、NLog ロガーを優れたサードパーティ ライブラリ コンシューマのようにラップするときに始まります。私は次のようなインターフェースを持っています
public interface ILog
{
...
void Error(string errorMessage, params string[] args);
void Error(Func<string> messageGenerator);
void Error(Exception excepetion, string errorMessage, params string[] args);
void Error(Exception excepetion, Func<string> messageGenerator);
...
}
次に、次のような実装
...
public void Error(Func<string> messageGenerator)
{
//_log is an NLog logger
_log.Error((LogMessageGenerator) messageGenerator);
}
....
私の問題は、エラー ログでラムダが評価されていないことです。私は少し遊んでみましたが、問題は Func が最初に作成されたときに単に Func として作成され、NLog に渡されると LogMessageGenerator ではなくそのまま渡されることだと思います。オブジェクトを受け入れる NLog オーバーロードが呼び出されます。したがって、ラムダをコンパイルしているとき、C#コンパイラはコンテキストに基づいて戻り値を静的に型付けしようとしていると推測しています。
//log is raw nlog logger
log.Error(()=> "I am a terrible error"); => LogMessageGenerator
//log is my wrapper
log.Error(()=> "I am an even more terrible error"); => Func<string>
メソッドの署名を変更して LogMessageGenerator を取得することにより、インターフェイスで NLog に明示的に依存することなく、NLog の正しいオーバーロードを呼び出すように ILog 実装を構築する方法はありますか? 私は素朴に Func を LogMessageDelegate にキャストしようとしましたが、それはうまくいきません。