GrabDuck

How to Add PostSharp to Your C# Project in 60 Seconds (a Simple AOP Introduction) - ...

:

Here is a simple and brief introduction to PostSharp and AOP style logging and monitoring.

We are going to create a simple Console application with a single class containing three basic methods, one of which will deliberately throw an exception. By doing this, we’ll gain an insight into the some of the powerful abilities of AOP style programming.

Now if you’ve found this blog, I assume you know what PostSharp is but in case you don’t, I’ll give you a very quick overview. PostSharp is a static AOP library which means it applies your “Aspects” at Compile time, which alters the byte code of your assembly file. Your Aspects are code classes written in C# which get code generated into behaviour based on the attributes you add to your code. For this example, our Aspects will be ouputting a message to the console on entry and exit of each method call.

And for more on PostSharp from the creators website, visit:

For further information on AOP, you can visit:

Wait up, what about the 60 seconds bit? Yes, you really can add PostSharp to your project in 60 seconds but before we start, we are going to download and install the PostSharp library and create a simple C# console app.

So first up, visit the SharpCrafters website to download the PostSharp library. At the time of writing this blog, the current version is v2.0 with a 45 day trial or community license.

Step two, let’s create our new console application and call it PostSharpIntro:

create console

Next up, we are going to add the following code to your Program.cs file:

using System;

namespace PostSharpIntro
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var calculator = new Calculator();
                int a = 7, b = 5, result;
                
                string message = "Welcome to the PostSharpIntro project";
                Console.WriteLine(message);

                result = calculator.Add(a, b);
                message = string.Format("{0} add {1} equals {2}", a, b, result);
                Console.WriteLine(message);

                result = calculator.Subtract(a, b);
                message = string.Format("{0} subtract {1} equals {2}", a, b, result);
                Console.WriteLine(message);

                calculator.RunUnstableCode();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                Console.WriteLine("Press any yet to exit...");
                Console.ReadKey();
            }
        }

        public class Calculator
        {
            internal int Add(int a, int b)
            {
                return a + b;
            }

            internal int Subtract(int a, int b)
            {
                return a - b;
            }

            internal void RunUnstableCode()
            {
                throw new Exception("Houston, we have a problem!");
            }
        }
    }
}

We have added a simple calculator class with methods to Add, Subtract and RunUnstableCode. We’ll call all three methods displaying each result to the console.

So you are now ready to press F5 and run your code.

console-window-1

So this is the interesting bit, adding PostSharp to your project. There are 4 easy steps so if you are ready with your stopwatch, let’s GO!

Step 1

Open Windows Explorer and navigate to the following PostSharp Samples directory:

C:\Program Files\PostSharp 2.0\Samples\.NET Framework 3.5\CSharp\Trace

Note: Where Program Files is the default folder for programs on your machine.

Step 2

Now add the aspects from the example project by dragging the Formatter.cs, QuickTraceAttribute.cs and FullTraceAttribute.cs files into your PortSharpIntro project.

Step 3

Add a Reference to the PostSharp library (right click on your project > Add Reference… > Browse)

Navigate to the following file and double click on it, then press the Add button: C:\Program Files\PostSharp 2.0\Release\PostSharp.dll

Step 4

The final part is to let our project know exactly what and where we should be logging. To do this, we need to add two new lines of code (highlighted below):

using System;

[assembly: Trace.QuickTrace(AttributeTargetAssemblies = 
"PostSharpIntro", AttributeTargetTypes = "PostSharpIntro.*")]

namespace PostSharpIntro
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Diagnostics.Trace.Listeners.Add
            (new System.Diagnostics.TextWriterTraceListener(Console.Out));

            try
            {
                var calculator = new Calculator();
                int a = 7, b = 5, result;
                
                string message = "Welcome to the PostSharpIntro project";
                Console.WriteLine(message);

                result = calculator.Add(a, b);
                message = string.Format("{0} add {1} equals {2}", a, b, result);
                Console.WriteLine(message);

                result = calculator.Subtract(a, b);
                message = string.Format("{0} subtract {1} equals {2}", a, b, result);
                Console.WriteLine(message);

                calculator.RunUnstableCode();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                Console.WriteLine("Press any yet to exit...");
                Console.ReadKey();
            }
        }

        public class Calculator
        {
            internal int Add(int a, int b)
            {
                return a + b;
            }

            internal int Subtract(int a, int b)
            {
                return a - b;
            }

            internal void RunUnstableCode()
            {
                throw new Exception("Houston, we have a problem!");
            }
        }
    }
}

Line 3: Log everything within our PortSharpIntro namespace. Notice that the PostSharp aspect files are not within this namespace, this is deliberate so we don’t log the aspects.

Line 11: Ensures that the log messages will be sent to the console window, but you can alter this to output to a text file, database, the event viewer, have combinations of multiple outputs, just about anything you like.

And that’s it - pretty simple, eh! Press F5 to run your application and you can see new messages appear.

final

The console window messages explained:

Line # Output Description
1 Entering PostSharpIntro.Program+Calculator..ctor PostSharp: On entry when instantiating new Calculator object
2 Leaving PostSharpIntro.Program+Calculator..ctor PostSharp: On exit when instantiating new Calculator object
3 Welcome to the PostSharpIntro project Our code
4 Entering PostSharpIntro.Program+Calculator.Add PostSharp: On entry when calling Calculator.Add
5 Leaving PostSharpIntro.Program+Calculator.Add PostSharp: On exit when calling Calculator.Add
6 7 add 5 equals 12 Our code
7 Entering PostSharpIntro.Program+Calculator.Subtract PostSharp: On entry when calling Calculator.Subtract
8 Leaving PostSharpIntro.Program+Calculator.Subtract PostSharp: On exit when calling Calculator.Subtract
9 7 subtract 5 equals 12 Our code
10 Entering PostSharpIntro.Program+Calculator.RunUnstableCode PostSharp: On entry when calling Calculator.RunUnstableCode
11 Leaving PostSharpIntro.Program+Calculator.RunUnstableCode with exception: Houston, we have a problem! PostSharp: On error when calling Calculator.RunUnstableCode
12 System.Exception: Houston, we have a problem! As above
13, 14 at PostSharpIntro.Program.Calcalculator.RunUnstableCode(Int32 a, Int32 b) in C:\Projects\PostSharpIntro\Program.cs : line 56 As above
15 Leaving PostSharpIntro.Program+Calculator.RunUnstableCode PostSharp: On exit when calling Calculator.RunUnstableCode
16 Houston, we have a problem! Our code
17 Press any key to continue… Our code

Pretty cool stuff! Now you’re probably thinking it would be useful to see which variables were passed into our method that throw the exception. Simply switch from QuickTrace to FullTrace:

using System;

[assembly: Trace.FullTrace
(AttributeTargetAssemblies = "PostSharpIntro", AttributeTargetTypes = "PostSharpIntro.*")]

namespace PostSharpIntro
{
    class Program
    {
        ...

And press F5 to see the values (.ToString()) for each of the parameter variables:

full-final-output

This example is using the Microsoft System.Diagnostics.Trace framework for its logging mechanism, but this could easily be swapped out for NLog, Log4Net or any other logging framework.

I hope this brief introduction into PostSharp and Aspect Oriented Programming helps, enjoy your programming!