Total votes: 0
Print: Print Article
Please login to rate or to leave a comment.
Published: 23 Mar 2011
An introduction to Aspect Oriented Programming (AOP) and PostSharp.
What is Aspect Oriented Programming?
"Aspect Oriented Programming is a programming paradigm which aims to increase modularity by allowing the separation of cross-cutting concerns." -
What does the above quote actually mean? It means that AOP allows you as a developer to focus on writing important code by not having to
deal with the mess of cross-cutting concerns. AOP can also take the pain out of writing boiler plate code and repetitive code by automating the
What are cross-cutting concerns?
The Separation of Concerns principal states that a concern is any piece of interest or focus in a program. Think about it in terms of a layered
architecture with the layers being UI, Business, Service and Data. Each one of these layers is its own concern. These layers are "horizontal".
layer is only concerned with display and user interaction and not with database connectivity; as such, the data layer is not concerned with determining if a
user is eligible for a car loan (business rules). When you design your code you usually break up these concerns into their own modules (classes, assemblies,
Logging, security, error handling and caching are also concerns but where do they fit in to this layered architecture? The answer is everywhere.
These concerns are "vertical" or "cross-cutting" which means they touch each layer. UI needs logging and error handling just as the other layers do
Why would you use Aspect Oriented Programming?
In simple terms, AOP allows you to write a block of code and inject it at certain points in your code automatically which results in faster development
times, consistency, maintainability and cleaner code. Following the Don't Repeat Yourself (DRY) principal is easy using AOP because you write code once and
only once. No copy & paste.
Problem: You're writing an application and you need to log exceptions. This is not a unique problem to solve but is an incredibly trivial part of
Old Solution: Wrap a try/catch around each method that requires logging and then add the logging code to the catch
AOP Solution: Create an aspect which contains the logging code. Apply the aspect to each method requiring logging.
scenario both the solutions are very similar but what impact does each solution have on the code? How scalable, clean, consistent, reliable and maintainable
are each solution?
Table 1: Advantages of an AOP-based solution.
Not scalable at all. Requires writing code constructs each time the functionality is required. As
more methods are added, more code has to be written.
Extremely scalable. Logging can be automatically applied to new methods as they are added
with no extra work or thought by the developer.
Can be clean depending on the size and complexity of the method. Adds at least 7 extra lines of
code per method.
Extremely clean because you're not adding any code to the methods.
Can be consistent depending on techniques used, but not guaranteed due to repetitive implementation
by the developer.
Extremely consistent because the code is coming from a single source and implemented automatically, not by the
As the redundancy increases the reliability decreases. Developers can forget and make
Very reliable since the code comes from and is maintained in a single location and distributed automatically.
Not very maintainable due to multiple points making it difficult and time consuming to
implement code changes.
Extremely maintainable because, again, the code is in a single spot. No find/replace required.
Based on this scenario it's clear that the AOP solution is far superior.
How do I use AOP? Introducing PostSharp
To take advantage of AOP in your development you need an AOP framework. The leading AOP framework is PostSharp by SharpCrafters. PostSharp makes
implementing AOP very simple and comes with many pre-built aspects that you just stick your code into and you're done.
PostSharp uses plain .NET
attributes that you build out and apply to targets such as assemblies, classes, methods and properties. PostSharp gives you full control of how and where
your aspects are applied.
How does it work? PostSharp does its work at build time after the compiler has generated the IL from your C# (or VB, if
you're a devil) to produce the final result using MSIL rewriting techniques. PostSharp is based on the PostSharp SDK which is the most advanced assembly
transformation platform available so you can be sure that the results are correct and consistent.
PostSharp not only allows you to specify exact
targets for your aspects but also allows you to specify at which level to apply them. For example, you could apply the logging aspect from our scenario above
to each method individually or you could apply it only on the containing class and let PostSharp apply to the methods automatically which saves you lines of
code and time. Some aspects need a greater scope like our logging aspect and will need to be applied to all classes in a project. To fulfill this requirement
you can add an assembly level declaration which tells PostSharp to automatically apply the aspect to all methods in all classes.
With the assembly
level declaration you no longer have to think about adding logging when adding new classes or methods because it will automatically be injected by PostSharp
at build time.
For more information on PostSharp you can visit SharpCrafters.com
For this example we're going to look at how easy it is to start using PostSharp, creating an aspect and applying it to targets explicitly and implicitly
while solving a real world problem.
There are many times where an exception will occur at the bottom of the call stack that will
bubble up to a caller higher in the stack that just swallows it. Swallowed exceptions can't be logged or fixed. This commonly happens when taking advantage
using statement, especially when working with WCF proxies.
Our example code shows how easily this can happen even in the simplest
of code. After recognizing the problem, we will use AOP to help us solve this issue.
If you have not done so already, download and
install the latest PostSharp 2.0. Once that's done start a new console application project from Visual Studio and add a reference to PostSharp. If you can't
find it in the GAC you can browse to it under the install folder \Reference Assemblies\.NET Framework 2.0\PostSharp.dll
the code in the program.cs file with the following code block
The output of this will be
But wait, only one exception was logged! That's because the other exception was swallowed by the using statement. Such a potentially huge
problem can be solved with the simplest application of AOP using PostSharp.
Creating your first aspectAdd a new class to your project called
LoggingAspect.cs and add the following code
All aspects require the 'serializable' attribute; you'll receive a compiler error if you don't decorate your aspects.
Our aspect is nothing more than an attribute that inherits from OnExceptionAspect which PostSharp was nice enough to provide for us to
handle all the nasty stuff we don't need to worry about. All we have to do is override a single method
OnException and populate it with the
code we want to use to do error logging. For this example we just output the info to the console.
LoggingAspect(AttributeExclude=true)] decoration is required for this example. We're telling PostSharp not to include
this class when applying the LoggingAspect attribute. If you don't include the decoration you will receive a build error if PostSharp tries to apply the
aspect to the aspect class. It could result in a stack overflow at runtime if it were allowed.
Applying the aspect
There many ways in which we can apply our aspect. To start, we'll add it explicitly to the method we know is throwing the
swallowed exception. Decorate the
TestMethod declaration our new attribute
Now when you run this code you will see that both exceptions are now being logged.
Scaling your solution
We could stop there and call it a day, but why not be consistent and apply our new logging code to all methods?
This can be done by decorating each method in the class with our attribute; but that can get messy and less maintainable if there were 20+ methods in our
class. Remove the attribute from
TestMethod and move it to the TestClass declaration
PostSharp will see that the class is decorated with our aspect attribute and automatically apply it to all methods in the class for us. If you
run the updated code the output will be
The output shows duplication for the Dispose method exception. Our aspect logs the error before it bubbles up to the try/catch. Any new methods
added will automatically receive our logging declaration. You can refactor the code to remove the redundant try/catch in the main method.
project is as simple as it gets but in the real world you could potentially have hundreds of classes. Decorating each class with our logging aspect just
isn't desirable. Thankfully, PostSharp allows us to apply aspects across the assembly.
Remove the attribute from TestClass and open the
AssemblyInfo.cs under the Properties folder in the project. At the bottom add the following line
This declaration tells PostSharp to apply our logging aspect to all types under the ConsoleApplication1 namespace using the wildcard syntax.
When you run the code now you will see the same result as before but the difference is whenever you add a new class it will automatically receive the
decoration and PostSharp will propagate to all methods in the class our logging aspect automatically.
You can't beat the automation of applying cross-cutting concerns and it's hard to deny how AOP and PostSharp can improve your development and cut
development time. PostSharp has much more power than our simple example. The more you use PostSharp and AOP the more uses you will find for it.
Dustin is a Microsoft C# MVP, Pluralsight author and producer of c0deporn.
This author has published 3 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.