On the last episode of my podcast, I interviewed Matt Groves about Aspect Oriented Programming (AOP). Talking with him inspired me enough to really make a go and spend some time with it to see if I could get comfortable with it. I’m going to try to use PostSharp because I like how it works and because (to be honest) they helped promote that last podcast, and that makes me like their style 😉
As Matt talked about in the podcast, AOP is basically a kind of design pattern. Essentially, you find stuff that is in your code and in a lot of methods, but doesn’t ACTUALLY pertain to the method. Common examples are logging, error handling, cache checks, and parameter checking, to name a few. Once you isolate this code that is basically boilerplate code that is used over and over again throughout your methods, you pull that code out and allow it to exist in only one place.
Frameworks like PostSharp act as post-compilers, so you write your code, add some attributes, and PostSharp will take an extra compiler pass through your code and write the code in for you, as if you had done it yourself. This allows for no additional runtime overhead, as the code works out to just basically be your standard code you would have written anyway.
To get started, head over to PostSharp’s site and download their product. It gets added as a Visual Studio extension and – as of today – you get a 45 day license to their full product when you download it. After that, it will revert to the free version. The free version still has a ton of great features and everything I’m doing today will work on only the free version.
To start with, I’m only going to make a console application that just does some simple string manipulation. You can see the entire project in its completed state on GitHub here.
After I created the project, I had to right click the project and select Add PostSharp to Project. This added a reference to PostSharp’s .dll and set PostSharp up in my packages config. Now, we can start making our first aspect. I’m going to tackle the “low hanging fruit” of some very simple logging first.
I’m going to keep this very simple, so I’m just going to do Console.WriteLines instead of complicating this project by integrating a complicated logging framework just to show an example. I have a Utility class with a ReverseString method. In addition to the “business logic” of actually reversing the string, I am also writing out every entry and exit to and from the method.
public class Utility { public string ReverseString (string input) { Console.WriteLine("Entering ReverseString at {0}", DateTime.Now.Ticks.ToString()); var inputArray = input.ToCharArray(); Array.Reverse(inputArray); Console.WriteLine("Leaving ReverseString at {0}", DateTime.Now.Ticks.ToString()); return new string(inputArray); } }
Calling that method with some test data gives me this output:
Now, every method I’d write, I’d have to dirty up with those WriteLines. It clutters up the code and makes it that much harder to understand. Let’s pull that out into an Aspect.
I add a plain C# class to my project called WriteLineAttribute.cs. The code for it is here:
using PostSharp.Aspects; using System; namespace IntroToAop1 { [Serializable] public class WriteLineAttribute : OnMethodBoundaryAspect { public override void OnEntry(MethodExecutionArgs args) { Console.WriteLine("Entering {0} at {1}", args.Method.Name, DateTime.Now.Ticks.ToString()); } public override void OnExit(MethodExecutionArgs args) { Console.WriteLine("Leaving {0} at {1}", args.Method.Name, DateTime.Now.Ticks.ToString()); } } }
Some things to point out. You have to mark the class as Serializable. This is just due to how PostSharp manages these things. Secondly, you just have to inherit from OnMethodBoundaryAspect. That is one of the built in Aspects that PostSharp offers for exactly what we want to do, operating coming in and out of methods. Now, to get my behavior, I just override the OnEntry and OnExit methods and put the Console.WriteLines in that I had before (making the method name dynamically generated from the arguments passed in to me).
Now, my ReverseString method looks like this:
[WriteLine] public string ReverseString (string input) { var inputArray = input.ToCharArray(); Array.Reverse(inputArray); return new string(inputArray); }
The WriteLines are gone and I just added the [WriteLine] attribute at the top of my method. Running that gives me this output:
Okay, maybe this intro isn’t “blow your mind impressive”, but it does show you some of the power to make clean code that PostSharp offers you. If I wanted to log something new, I only have to change it in one place. If I wanted to make that logging come on and off based on a compile flag or a configuration value, again it is a single point of change. And the fact that my results are exactly the same (except for the timestamps) means that I had a successful refactor while cleaning up my code.
Again, if you want to play around with the code, you can find it on GitHub. I’ve added some more string manipulation methods just to further show how much nicer the code will look “PostSharp’ed”.
Next time, I’m going to use PostSharp to validate the parameters on my methods so that they don’t blow up when you pass in null values!