C#/AOP: Elegant tracing with PostSharp and Aspect-Oriented Programming


My post yesterday was about Python decorators and in that post I used the example of tracing to illustrate how to use Michele Simionato’s decorator module.

As a fan of comparative code samples, with this post I’ll show you how to accomplish the same thing with C#.

Unlike the Python sample, it’ doesn’t involve using another library. Instead this solution requires the use of an Gael Fraiteur’s Aspect-Oriented tool called PostSharp.

 

The Starting Point

Let’s look at the base source code. It’s just a method called foo() that prints “Hello World”

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DemoPostSharpTracing
{
    class Program
    {

        static void foo()
        {
            System.Console.WriteLine("Hello World");
        }

        static void Main(string[] args)
        {
            foo();
        }
    }
}

 

This is the output.

snap0020

Now let’s add some tracing

First install PostSharp 1.0

snap0003 snap0005 snap0006 snap0007snap0011snap0012

Add References to these two assemblies

– PostSharp.Laos

– PostSharp.Public

 

   snap0021 snap0023

 

Now create an attribute that prints an entry and exit message.

 

 

    [Serializable]
    public class TraceAttribute : PostSharp.Laos.OnMethodBoundaryAspect
    {
        public override void OnEntry(PostSharp.Laos.MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("ENTER {0}.", eventArgs.Method);
        }

        public override void OnExit(PostSharp.Laos.MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("EXIT {0}.", eventArgs.Method);
        }
    }

 

The name of the attribute class is “TraceAttribute” so just add “Trace” as an attribute to foo()

 

        [Trace]
        static void foo()
        {
            System.Console.WriteLine("Hello World");
        }

 

So the full source code will look like this. Red marks the changes from the code we started with.

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DemoPostSharpTracing
{

    [Serializable]
    public class TraceAttribute : PostSharp.Laos.OnMethodBoundaryAspect
    {
        public override void OnEntry(PostSharp.Laos.MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("ENTER {0}.", eventArgs.Method);
        }

        public override void OnExit(PostSharp.Laos.MethodExecutionEventArgs eventArgs)
        {
            Console.WriteLine("EXIT {0}.", eventArgs.Method);
        }
    }


    class Program
    {

        [Trace]
        static void foo()
        {
            System.Console.WriteLine("Hello World");
        }

        static void Main(string[] args)
        {
            foo();
        }
    }
}

 

 

And this is the output

snap0027

Nice!

Now we can simply turn on tracing for a function just by annotating it with the [Trace] attribute.

 

Parting Thoughts

  • Please keep in mind I picked the simplest possible example. You can do more with PostSharp and AOP that tracing.
  • Notice the [Serializable] attribute on the TraceAttribute class. This was necessary for me to get project to compile. However, it’s not entirely clear to my why the the class needed to this attribute.
  • One of the great features of PostSharp is that it integrated with the MSBUILD process so that there were no extra configuration steps – it works “out-of-the-box”.

Comments (1)

  1. Stanislav says:

    Is not so elegant, because you have to modify all your classes (add attribute) to be traced, wich is really not so for why aspect most of time is used

Skip to main content