PostSharp.Samples / PostSharp.Samples.ExceptionHandling / AddContextOnExceptionAttribute.cs
using PostSharp.Aspects;
using PostSharp.Serialization;
using System;
using System.Text;
 
namespace PostSharp.Samples.ExceptionHandling
{
  /// <summary>
  ///   Aspect that, when applied to a method and whenever this method fails with an exception, adds the value of method
  ///   parameters to the <see cref="Exception" /> object.
  ///   The <see cref="ReportAndSwallowExceptionAttribute" /> can consume this information and print it if the exception is
  ///   not handled.
  /// </summary>
  [PSerializable]
  public sealed class AddContextOnExceptionAttribute : OnExceptionAspect
  {
    /// <summary>
    ///   Method invoked when the target method fails with an exception.
    /// </summary>
    /// <param name="args">Method invocation context.</param>
    public override void OnException(MethodExecutionArgs args)
    {
      // Get or create a StringBuilder for the exception where we will add additional context data.
      var stringBuilder = (StringBuilder) args.Exception.Data["Context"];
      if (stringBuilder == null)
      {
        stringBuilder = new StringBuilder();
        args.Exception.Data["Context"] = stringBuilder;
      }
 
      // Append context to the StringBuilder.
      AppendCallInformation(args, stringBuilder);
      stringBuilder.AppendLine();
    }
 
    private static void AppendCallInformation(MethodExecutionArgs args, StringBuilder stringBuilder)
    {
      var declaringType = args.Method.DeclaringType;
      Formatter.AppendTypeName(stringBuilder, declaringType);
      stringBuilder.Append('.');
      stringBuilder.Append(args.Method.Name);
 
      if (args.Method.IsGenericMethod)
      {
        var genericArguments = args.Method.GetGenericArguments();
        Formatter.AppendGenericArguments(stringBuilder, genericArguments);
      }
 
      var arguments = args.Arguments;
 
      Formatter.AppendArguments(stringBuilder, arguments);
    }
  }
}