5

私はlog4netを使用しており、コードにはこれがたくさんあります:

public class Foo {
    private static readonly ILog log = LogManager.GetLogger(typeof(Foo));
    ....
}

欠点の 1 つは、この 10 語のセクションをあちこちに貼り付けることになり、ときどき誰かがクラス名を変更するのを忘れてしまうことです。log4net FAQでは、この別の可能性についても言及されていますが、これはさらに詳細です。

public class Foo {
    private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    ...
}

これを定義するデコレータを書くことは可能ですか? 私は本当に簡単に言いたいです:

[LogMe]  // or perhaps: [LogMe("log")]
public class Foo {
    ...
}

私は他の言語で同様のことを行ったことがありますが、C# のような静的にコンパイルされた言語では決して行いませんでした。デコレーターからクラス メンバーを定義できますか?

編集:へー。私は Lisp プログラマーです。言語を切り替えるという提案には感謝していますが、実際には、より優れたメタプログラミング機能のために言語を切り替える場合は、中途半端になるのではなく、Lisp に行きます。残念ながら、このプロジェクトでは別の言語を使用することはできません。

4

8 に答える 8

5

これはまさに AOP (アスペクト指向プログラミング) のタスクです。PostSharpを見てください。これは .NET AOP フレームワークであり、必要なことを正確に行うことができます。

これは、ポストコンパイルで IL コードを変更 (または織り込み) し、装飾されたメソッドにロギングの側面を追加することで機能します。

編集: PostSharp は現在商用製品のようです。オープンソース (無料) のソリューションを探しているなら、LinFu AOPをお勧めします。

于 2010-05-17T21:30:47.943 に答える
3

ほぼ同じものを使用します。

private static readonly ILog Logger = LogManager.GetLogger();

このメソッドは次のように実装されます。

[MethodImpl(MethodImplOptions.NoInlining)]
public static ILog GetLogger()
{
    Type t;
    try { t = new StackFrame(1, false).GetMethod().DeclaringType; }
    catch { t = typeof(UnknownObject); }
    return GetLogger(t);
}
private static class UnknownObject { }

それは私が経験したいと思っているよりも多くの苦痛であることがまだ証明されています. 私は、ロギング用の静的メソッドを持つ静的オブジェクトを好みます。ファイル情報を取得しなければ、呼び出しメソッドを取得するのにそれほど費用はかかりません。Log4Net を呼び出して呼び出しタイプを取得するだけの費用と比較すると、(使用するロガーによっては) 何もありません。

于 2010-05-17T21:50:12.283 に答える
1

.NET の属性は、アタッチされているクラス/メンバーに影響を与えるデコレータ/アクティブ コンポーネントではありません。属性は、リフレクションで取得できるメタデータです。C# にはデコレータのような機能はありませんが、必要に応じて .NET を拡張する AOP ソリューションがあります。ただし、最も簡単な解決策は、おそらくその行を各クラスにコピーすることです。

于 2010-05-17T21:27:46.497 に答える
1

簡単に切り替えることができるように、log4net をラップしました。これは、将来的に考えを変える可能性が非常に高いものです。

私たちはこれを行っていませんが、おそらくそうするとパフォーマンスが低下するでしょう....そして、それが良い考えであるかどうか確信が持てないので、私はそれを提案することさえ本当に躊躇しています.... ...あなたが十分に悪魔だと感じたら....log4netをラップし、ラッパーでこのようなことをしてください。

var callingType = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType

ロギングの方法を熟知していれば、ログ メッセージが必要な場合にのみそのコストが発生する可能性があります。

于 2010-05-17T21:49:32.033 に答える
0

これが ASP.NET または Windows フォームの場合、すべてのフォーム/ページの派生元であるベース ページまたはベース フォームを作成できます。このメンバーをそのレベルで宣言すると、おそらく目的を達成できます。

于 2010-05-17T21:30:51.517 に答える
0

おそらく、 PostSharpや別のアスペクト指向プログラミング ツールを使用して、これに対する解決策を実装できます。

Boo でマクロを使用するのはかなり簡単ですが、それはあなたの状況をあまり助けません。

于 2010-05-17T21:31:21.920 に答える
0

おそらく簡単な方法は、インターフェイスに拡張メソッドを記述することです。その後、クラスはインターフェイスを「実装」する必要があります (ただし、拡張機能が impl を実行するため、実際にはそうではありません)。

public class Foo : IGetLog<Foo>
{

}

みたいな拡張子....

  public interface IGetLog<T> { }

  public static class IGetLogExtension
  {
    public static ILog GetLogger<T>(this IGetLog<T> getLog)
    {
      return LogManager.GetLogger(typeof(T));
    }
  }
于 2010-05-17T21:33:19.047 に答える
0

男これはpythonで簡単です。私はC#属性を調べます。

于 2010-05-17T21:27:14.810 に答える