Heute habe ich mich sehr gefreut, als ich meinen E-Mail-Briefkasten geöffnet habe. Die Firma PostSharp stellt unentgeltlich das gleichnamige Produkt „PostSharp 3.0 – Ultimate“ zur Weiterentwicklung des CorpusExplorers zur Verfügung. Vielen Dank dafür!

Als kleines Dankeschön schon einmal einen ersten Auszug aus dem Aspekt der Fehler und Performance im CorpusExplorer protokolliert. Der Aspekt nutzt sowohl PostSharp als auch Log4Net zur Protokollierung (beides muss installiert sein):

[csharp]
#region usings

using System;
using System.IO;
using System.Reflection;
using System.Text;
using log4net;
using log4net.Config;
using PostSharp.Aspects;

#endregion

namespace CorpusExplorer.Sdk.Data.Aspekte
{
///

/// Aspekt zum dekorieren von Methoden. Fängt automatisch Fehler ab und (falls Debug-gesetzt) erstellt ein Tracinglog.
///

[Serializable]
public class ErrorReportingAndTracingAspect : OnMethodBoundaryAspect
{
///

/// Zeitstempel wird von OnEntry gesetzt und von OnSuccess gelesen
///

private static DateTime _stamp;

///

/// Standardwert, der im Fehlerfall (OnException) zurückgegeben wird
///

private readonly object _defaultReturn;

///

/// Speichert ob ein Standardwert hinterlegt wurde
///

private readonly bool _hasDefaultValue;

///

/// Konstruktor für alle void-Methoden sowie alle nicht-void-Methoden
/// bei denen die Exception durchgereicht werden soll.
///

public ErrorReportingAndTracingAspect()
{
_hasDefaultValue = false;
}

///

/// Setzt einen Standardwert, der im Fehlerfall zurückgeben wird.
/// Hinweis: darf -NICHT- für void-Methoden verwendet werden.
///

public ErrorReportingAndTracingAspect(object defaultReturn)
{
_defaultReturn = defaultReturn;
_hasDefaultValue = true;
}

///

/// Mapping für Typdefinition
///

private Type Type { get { return MethodBase.GetCurrentMethod().DeclaringType; } }

///

/// Wird aufgerufen, wenn die dekorierte Methode einen Fehler (Exception) auslöst
///

///MethodExecutionArgs public override void OnException(MethodExecutionArgs args)
{
LogManager.GetLogger(Type).Error(null, args.Exception);

if (_hasDefaultValue)
{
args.ReturnValue = _defaultReturn;
// Tue so, als wäre nichts passiert. Die Exception gilt als behandelt/unterdrückt.
args.FlowBehavior = FlowBehavior.Return;
}
else
{
args.FlowBehavior = FlowBehavior.Continue;
}
}

///

/// Wird aufgerufen, wenn die Methode betreten wird (vor der eigentlichen Ausführung).
///

///MethodExecutionArgs public override void OnEntry(MethodExecutionArgs args)
{
// Setze den Zeitstempel zum späteren Tracing.
_stamp = DateTime.Now;

// Lade Log4Net
XmlConfigurator.ConfigureAndWatch(new FileInfo(„log4net.config“));

// Wenn die Methode mit Parametern aufgerufen wird dann werden alle Parameter protokolliert.
// Hinweis: Die Protokollierung erfolgt nur, wenn DEBUG in log4net.config gesetzt ist.
if (args.Arguments.Count == 0)
{
LogManager.GetLogger(Type)
.DebugFormat(„{0} gestartet {1}“,
args.Method.Name,
_stamp);
}
else
{
var values = new StringBuilder();
foreach (var argument in args.Arguments)
values.Append(argument).Append(„,“);

LogManager.GetLogger(Type)
.DebugFormat(„{0} gestartet {1} mit foglenden Parametern: {2}“,
args.Method.Name,
_stamp,
values);
}
}

///

/// Wird aufgerufen wenn die Methode erfolgreich verlassen wird.
///

///MethodExecutionArgs public override void OnSuccess(MethodExecutionArgs args)
{
// Protokolliert das erfolgreiche Ende sowie den möglichen Rückgabewert.
// Hinweis: Die Protokollierung erfolgt nur, wenn DEBUG in log4net.config gesetzt ist.
if (args.ReturnValue == null)
LogManager.GetLogger(Type)
.DebugFormat(„{0} erfolgreich beendet nach {1}ms – (Rückgabe: void/null)“,
args.Method.Name,
(_stamp – DateTime.Now).Milliseconds);
else
LogManager.GetLogger(Type)
.DebugFormat(„{0} erfolgreich beendet nach {1}ms – (Rückgabe: {2})“,
args.Method.Name, (_stamp – DateTime.Now).Milliseconds, args.ReturnValue);
}
}
}
[/csharp]