5

メソッドを呼び出すたびに文字列形式を使用する必要がないように、形式と引数のリストを渡すことができるように、いくつかの便利な拡張メソッドで拡張するロギングインターフェイスがあります。(FXCopsカルチャー情報ルールに従うのにも役立ちます)

だから私は呼び出すことができます:

logger.Debug("Created {0} with id {1}",typeof(MyObject).Name ,myObject.Id);

それ以外の:

logger.Debug(string.Format("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id));

ファイル、メソッド、行番号など、ログが書き込まれた場所に関する情報もログに取得すると非常に役立つため、少し注意が必要な状況になりました。[CallerMemberName]これは、きちんとした、、、[CallerFilePath]および[CallerLineNumber]属性を使用して実現できます。

logger.Debug("Created {0} with id {1}", typeof(MyObject).Name, myObject.Id);

次に、次のようなログエントリが表示されます。

"MyObjectProvider.cs、Provide、line:50 |ID1564でMyObjectを作成しました"

ここでの問題は、メソッドシグネチャが次のようになることです。

public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0, params object[] args)

[Caller*]属性によってパラメーターがオプションになり、argsパラメーターでは機能しないため、これは不可能です。

また、次のようなパラメータとして、固定量の文字列を使用して複数の実装を作成しようとしました。

public static void Debug(this ILogger logger, string format [CallerMemberName] string callerMemberName = "",string arg, string arg2 , ...etc... , [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)

しかし、 「次のメソッドまたはプロパティ間で呼び出しがあいまいです」というコンパイラエラーが発生します。

私は今この問題をほとんどあきらめていますが、私は自分自身に「多分SOは私のための解決策を見つけることができるだろう」と思いました。だからここにあります...両方を使用することは可能params object[] argsです[CallerFilePath]か、それとも意図した結果を得る別の方法がありますか?

4

5 に答える 5

1

メソッド シグネチャで 2 つを組み合わせることはできません。あなたができることは、どちらかでnullあり、オプションのパラメーターが必要な場所に渡すことです。これはうまくいきますか?

Foo(s, null);
public void Foo(string s, params string[] sArray)
{

}

Foo(new string[] {""});
private static void Foo(string[] sArray,  string s = "")
{
}

また

フォーマットを処理するクラスを使用して、それをオプションにしてみませんか?

public class LogArgs
{
  private string _formatString;
  private string[] _args;
  public LogArgs(string formatString, params string[] args)
  {
    _formatString = formatString;
    _args = args;
  }
  public override string ToString()
  {
    return string.Format(_formatString, _args);
  }
}

public void Foo(string mandatory, LogArgs optionalParam = null)
{
  //Do Stuff
}

Foo("", new LogArgs("{0} is formatted", ""));
于 2013-01-24T16:12:33.350 に答える
1

StackTrace を使用して、必要な情報を取得する別の方法を見つけました。最適化されたコードでは少し安全ではなく、非常に遅いですが、リリース ビルドでオフにできる限り、デバッグの目的でうまく機能します。

StackTrace stackTrace = new StackTrace();
var callerMember = stackTrace.GetFrame(1).GetMethod();
var callerMemberName = callerMember.Name;
var callerType = callerMember.ReflectedType.Name;
于 2013-01-25T09:16:15.087 に答える
0

私が見つけた最も洗練された方法 (または最も洗練されていない方法) は、属性情報を抽出してActionデリゲートを返す必要な名前のメソッドを作成することです。次に、実際に呼び出したい署名でこのデリゲートをセットアップします。

だから、から

public static void Debug(this ILogger logger, string format, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0, params object[] args)

デリゲートを作成する

public delegate void LogDelegate(string format, params object[] args);

メソッド呼び出しから返されます:

public static void Debug(this ILogger logger, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "", [CallerLineNumber] int callerLineNumber = 0)
{
  return (format, args)
  {
    LogWithCallerSiteInfo(format, args, callerMemberName, callerFilePath, callerLineNumber, logAction);
  }
}

キャプチャされたデータを使用してヘルパー メソッドを呼び出します。

private static void LogWithCallerSiteInfo(string format, object[] args, string callerMemberName, string callerFilePath, int callerLineNumber, Action<string, object[]> logRequest)
    {
        if (args == null)
        {
            args = new object[0];
        }
        var args2 = new object[args.Length + 3];
        args.CopyTo(args2, 0);
        args2[args.Length] = sourceFile;
        args2[args.Length + 1] = memberName;
        args2[args.Length + 2] = lineNumber;

        logRequest(format + " [{callerFilePath:l}.{callerMemberName:l}-{callerLineNumber}]", args2);
    }

そして、次のように呼び出しを行います。

logger.Debug()("Created {0} with id {1}",typeof(MyObject).Name ,myObject.Id);

したがって、使用法では、追加の のセットを挿入します()。これは、呼び出しサイト情報をキャプチャし、セット set がデリゲートで呼び出しを行います。それは私がそれを作ることができたのと同じくらいきれいです。

キャプチャしたデータを追加して配列を再作成しましたparams。それ以外の場合は (少なくともSeriLogでは、結果は予測できません。

于 2016-03-13T17:43:40.990 に答える
-2

すべてのデフォルト引数を右に移動します。

于 2013-01-24T16:12:25.303 に答える