parameter - summary c# returns




Generische Protokollierung von Funktionsparametern in der Ausnahmebehandlung (5)

Ein Großteil meines C # -Codes folgt diesem Muster:

void foo(string param1, string param2, string param3)
{
    try
    {
         // do something...
    }
    catch(Exception ex)
    {
        LogError(String.Format("Error in foo(param1={0}, param2={1}, param3={2}), exception={3}", param1, param2, param3, ex.Message));
    }
}

Gibt es eine Möglichkeit in .NET, eine Schlüssel / Wert-Liste der Parameter zu einer Funktion zu erhalten, so dass ich eine andere Funktion aufrufen kann, um meine Fehlerprotokollierungszeichenfolge zu erstellen? ODER Haben Sie einen allgemeineren / besseren Weg dies zu tun?


Nein, es gibt keinen Weg dies zu tun.

Normalerweise werden Ausnahmen nicht erfasst, es sei denn, Sie können mit ihnen umgehen.

Dh Sie würden normalerweise nur Exceptions abfangen und sie in einem Exception-Handler der obersten Ebene protokollieren. Sie erhalten dann einen Stack-Trace, erhalten aber natürlich keine Details über alle Parameter aller Methodenaufrufe im Stack.

Offensichtlich wollen Sie beim Debuggen so viele Details wie möglich haben. Andere Möglichkeiten, dies zu erreichen, sind:

  • Verwenden Sie Debug.Assert-Anweisungen großzügig, um die von Ihnen gemachten Annahmen zu testen.

  • Instrumentieren Sie Ihre Anwendung mit Protokollierung, die selektiv aktiviert werden kann. Ich benutze Log4Net, aber es gibt auch andere Alternativen, einschließlich der Verwendung der System.Diagnostics.Trace-Klasse.

Wenn Sie Ausnahmen nur abfangen, um sie zu protokollieren (ich würde dies an einer Tiergrenze in einer n-Tier-Anwendung tun, damit Ausnahmen auf dem Server protokolliert werden), sollten Sie sie immer erneut versuchen:

try
{
    ...
}
catch(Exception ex)
{
    log(ex);
    throw;
}

Sie könnten Reflection und die Konvention verwenden, dass Sie die Parameter in der richtigen Reihenfolge an LogError übergeben müssen:

private static void MyMethod(string s, int x, int y)
{
    try
    {
        throw new NotImplementedException();
    }
    catch (Exception ex)
    {
        LogError(MethodBase.GetCurrentMethod(), ex, s, x, y);
    }
}

private static void LogError(MethodBase method, Exception ex, params object[] values)
{
    ParameterInfo[] parms = method.GetParameters();
    object[] namevalues = new object[2 * parms.Length];

    string msg = "Error in " + method.Name + "(";
    for (int i = 0, j = 0; i < parms.Length; i++, j += 2)
    {
        msg += "{" + j + "}={" + (j + 1) + "}, ";
        namevalues[j] = parms[i].Name;
        if (i < values.Length) namevalues[j + 1] = values[i];
    }
    msg += "exception=" + ex.Message + ")";
    Console.WriteLine(string.Format(msg, namevalues));
}

Wenn ich das getan habe, habe ich nur ein generisches Wörterbuch für die Protokollierung erstellt.

Ich habe diese LogArgs-Klasse. Und eine Basisklasse anmelden, die ich anrufe, wenn ich eine Ausnahme habe.

public class LogArgs
{

    public string MethodName { get; set; }
    public string ClassName { get; set; }
    public Dictionary<string, object> Paramters { get; set; }


    public LogArgs()
    {
        this.Paramters = new Dictionary<string, object>();
    }

}

Dann am Anfang jeder Methode, die ich mache

LogArgs args = new LogArgs { ClassName = "ClassName", MethodName = "MethodName" };
args.Paramters.Add("Param1", param1);
args.Paramters.Add("Param2", param2);
args.Paramters.Add("Param3", param3);

base.Logger.MethodStartLog(args);

Wenn ich einen Fehler habe, logge ich es so ein.

base.Logger.LogError(args, ex);

Es gibt Szenarien mit wenigen Parametern oder Große Anzahl von Parametern ...

  1. Wenige Parameter, ohne viel Mühe, schreiben Sie sie besser als Teil der Logging / Exception-Nachricht.

  2. In großen Parametern würde eine mehrschichtige Anwendung ENTITIES (wie customer, CustomerOrder ...) verwenden, um Daten zwischen Layern zu übertragen. Diese Entitäten sollten Override-ToString () - Methoden der Klasse Object implementieren,

Logmessage ("Methode gestartet" + paramObj.ToString ()) würde die Liste der Daten im Objekt geben .. Irgendwelche Meinungen? :)

Vielen Dank


Dies ist ein wenig veralteter Beitrag, aber nur für den Fall, dass jemand auf diese Art und Weise auftaucht, wie ich es tat - ich löste dieses Problem mit PostSharp .

Es ist jedoch nicht praktisch frei. Die Express-Lizenz (über NuGet in VS herunterladbar) ermöglicht es Ihnen, Ihre Methode mit dem [Log] -Attribut zu dekorieren und dann Ihren bereits konfigurierten Logging-Mechanismus wie log4net nLog usw. zu wählen . Nun werden Sie Debug-Level-Einträge in Ihrem Log sehen und Parameterdetails angeben .

Mit Express-Lizenz konnte ich in meinem Projekt nur maximal 50 Methoden dekorieren. Wenn es Ihren Bedürfnissen entspricht, sind Sie gut zu gehen!







.net