32 Stimmen

Allgemeine Protokollierung von Funktionsparametern bei der Ausnahmebehandlung

Ein großer 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 Key/Value-Liste der Parameter zu einer Funktion zu erhalten, so dass ich eine andere Funktion aufrufen kann, um meine Fehlerprotokollierungszeichenfolge zu konstruieren? ODER Haben Sie eine allgemeinere / bessere Möglichkeit, dies zu tun?

0 Stimmen

Vielleicht etwas mit Reflexion in der Sprache, das helfen könnte?

0 Stimmen

Sie können es über Reflexion tun, aber es wird teuer im Laufe der vielen Funktionsaufrufe.

3 Stimmen

Ich glaube nicht, dass Sie dies mit Reflection oder StackTrace/StackFrame tun können. Ich denke, Ihre einzige Wahl kann sein, ein AOP oder Post-Processing-Framework, wie PostSharp zu verwenden.

37voto

Panos Punkte 18703

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));
}

0 Stimmen

Gut gemacht. Wie behandelt man ein Objekt wie eine Person oder einen Benutzer?

0 Stimmen

Jeeva Jsb for objects you can try to use some json serialization, e: <code> string output = JsonConvert.SerializeObject(user); </code>

8voto

Jacob Punkte 21787

Sie können die aspektorientierte Programmierung mit PostSharp verwenden (sehen Sie sich http://www.postsharp.org und das Lernprogramm unter http://www.codeproject.com/KB/cs/ps-custom-attributes-1.aspx ). Im Grunde könnte man so vorgehen:

public class LogExceptionAttribute : OnExceptionAspect
{
 public override void OnException(MethodExecutionEventArgs eventArgs)
 {
  log.error("Exception occurred in method {0}", eventArgs); 
 }
}

[LoggingOnExceptionAspect]
public foo(int number, string word, Person customer)
{
   // ... something here throws an exception
}

Vielleicht nicht ganz das, was Sie wollen, aber ich bin sicher, dass es an Ihre Bedürfnisse angepasst werden kann.

0 Stimmen

1 Stimmen

Postsharp.org existiert nicht mehr

5voto

Joe Punkte 117971

Nein, es gibt keine Möglichkeit, dies zu tun.

Normalerweise werden Ausnahmen nicht abgefangen, es sei denn, man kann sie behandeln.

D.h. Sie würden normalerweise nur Ausnahmen abfangen und in einem Top-Level-Exception-Handler protokollieren. Sie erhalten dann einen Stack-Trace, aber natürlich keine Details zu allen Parametern aller Methodenaufrufe im Stack.

Bei der Fehlersuche wollen Sie natürlich so viele Details wie möglich. Andere Möglichkeiten, dies zu erreichen, sind:

  • Verwenden Sie Debug.Assert-Anweisungen großzügig, um Ihre Annahmen zu testen.

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

Wenn Sie Ausnahmen nur abfangen, um sie zu protokollieren (ich würde dies in einer n-Tier-Anwendung an einer Schichtgrenze tun, damit Ausnahmen auf dem Server protokolliert werden), sollten Sie sie auf jeden Fall zurückwerfen:

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

0 Stimmen

Dadurch wird der Stapel abgewickelt, was bedeutet, dass unterschiedliche Aufrufe des Stapels protokolliert werden, als dass sie wieder verworfen werden. Um dies zu umgehen, ist es nun möglich, die Vorteile von Ausnahmefiltern zu nutzen: try { // ... } catch (Exception ex) when (log(ex)) { // never entered } wobei die Funktion log gibt immer zurück false .

1 Stimmen

Solange Sie nicht throw ex; und stattdessen nur throw; der Stapel und die Ausnahme bleiben bestehen.

1voto

David Basarab Punkte 69965

In diesem Fall habe ich einfach ein allgemeines Wörterbuch für die Protokollierung erstellt.

Ich habe diese LogArgs-Klasse. Und die Protokollierung in einer Basisklasse, die ich aufrufe, 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 mache ich am Anfang jeder Methode

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, protokolliere ich ihn auf diese Weise.

base.Logger.LogError(args, ex);

4 Stimmen

Interessanter Gedanke, aber wenn Sie sich selbst sagen hören: "Am Anfang jeder Methode mache ich X", sollten Sie die Verwendung eines AOP-Frameworks (wie PostSharp, wie von anderen Benutzern vorgeschlagen) in Betracht ziehen.

1voto

JoshL Punkte 10418

Sie können die Meldung in ähnlicher Weise aufbauen, aber das Schlüsselwort params in Ihrer LogError-Methode hinzufügen, um die Argumente zu behandeln. Zum Beispiel:

    public void LogError(string message, params object[] parameters)
    {
        if (parameters.Length > 0)
            LogError(string.Format(message, parameters));
        else
            LogError(message);
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X