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”.