CodeProject
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:
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.
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.
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:
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!