Posts Tagged ‘ Enterprise Library ’

Learning PostSharp

AOP from the Trenches

Aspect Oriented Programming feels alot like applying style sheets to a web site. Changing your ‘aspects’ will change the way your program works without having to make any changes to your code.

A few months ago I saw a great demo on PostSharp by Omar Besiso and I remember thinking, must ‘check that out someday‘.

Well amazingly, someday just rolled around and I started looking at PostSharp more closely and see if it could help me. My project needs logging and exception handling to be added so we are using the enterprise library blocks and I was keen to see how PostSharp might make my life easier.

The documentation on PostSharp is good but it’s a bit thin on best practice examples and little ‘gotchas’ so this blog entry is just a little collection things I am learning along the way…note that I am completely new to Aspect Oriented programming so please correct me if I say somethings really stupid or ignorant 🙂

There are also a couple of good articles on CodeProject to help you get started.

1. Restart Visual Studio

So I installed PostSharp, followed the quickstart sample exactly, compiled…didn’t seem to do anything. Ok so open up Reflector, did it actual make any changes? Nope.

After scrounging around the documentation for a while and trying various things to figure out what I was doing wrong I finally went back to the website ‘getting started’ section and in step two it clearly says ‘restart visual studio’.

Of course! Did that…all works.

And how good is this….I tweeted a hotip to restart VS after installing PS and within an hour I got message from Gael Fraiteur (the author) saying he’d raised a bug to warn users to restart VS after installing!

2. Don’t Try/Catch

These next few points all relate to handling exceptions with Aspects.

Let’s say you add this attribute to a method (and you’ve set them up properly):

[MyExceptionHandlerAspect(“MyExceptionPolicy”)]
public void MyMethod()
{
try
{
// exception happens here
}
catch(Exception ex) {// do something with the error
}
}

If you then do a try/catch like I have in the method then that try/catch takes over and the Aspect no longer ‘handles’ the exception. Which is good I think, you want to be able to ‘override’ what the aspect does in some instances. It feels a bit strange though, NOT wrapping a potentially naughty bit of code in a try/catch block, you have to have faith that the aspect will do its job.

NOTE: I’m not saying never use a try/catch block anymore, you will often still want to catch and specifically handle some exceptions.

3. Where Does FlowBehavior.Continue From?

I used eventArgs.FlowBehavior = FlowBehavior.Continue; and I expected the code execution to continue from (next line) where the exception occured. It didn’t, it returned to the line of code that called the method where the exception occurred. Consider the following:-

exceptionContinue

When the exception occurs in the Third method, my aspect handles it by doing whatever and then sets eventArgs.FlowBehaviour = FlowBehaviour.Continue; The result of this is execution continues in the Second method…and the Fourth method is not called.

Cool, not quite what I expected but it’s fine, the main thing is understanding how it works.

So what happens if we move that attribute?

exceptionContinue2

Well, here exception occurs in Third, but the aspect handles it in Second and so execution continues in First. Nice, just be aware of where you are putting the attribute.

We could also do this…

exceptionContinue3

Here, the exception occurs in Third and the aspect handles in Third also, so execution resumes in Two.

Note you can also put the attribute on the class, which saves you from putting it on individual methods. Seems to me that the best place to wire up the exception handlers are in the AssemblyInfo.cs files. This is what you need to add:-

[assembly:  MyExceptionHandlerAspect(“MyExceptionPolicy”)]

which to me is also much less confusing than attributes here and there randomly scattered through your code. Plus one of the big advantages of using PostSharp is that there is almost zero change required to existing code. So my ‘guess’ as to best practice here is to only apply an Exception Handling Aspect Attribute to individual methods when there is a very specific need to handle raised exceptions differently (i.e. use a different aspect or perhaps the same aspect with different parameters supplied – eg. in the case above I might want to use a different exception policy).

4. Continue After Exception – ‘Problem’

Just to be clear I don’t see this as a problem with PostSharp, it’s just a stumbling block I ran into.

I’m using the enterprise library, specifically for this problem I’m using the Exception Handling block. I have a policy to ‘handle’ System.Exception’s by logging them and then rethrowing an new exception that just wraps the original one.  Since all exceptions derive from System.Exception this handler will catch all exceptions except those that have their own explicitly defined handler (including the null reference exception below).

To the relevant AssemblyInfo.cs f iles I have added [assembly:  MyExceptionHandlerAspect(“MyExceptionPolicy”)].

Now I am also using CAB and discovered this ‘continue problem’ in a command handler.

commandHandler

I’ve added a dodgy bit of code that forces a null reference exception.

So, my PostSharp aspect looks like this

exceptionAspect

and it nicely does intercept my null reference exception but what happens when the call to HandleException is made? The enterprise library takes over and does it’s thing, logs and wraps the exception in a new exception which is returned in exceptionToThrow….great, so far so good.

The next thing that is going to happen is exceptionToThrow…will be thrown. But let’s see what the call stack looks like BEFORE it gets rethrown….

callStack1

At the top of the stack is the breakpoint I set in the OnException method in the OnExceptionAspect class. No problem, next is the OnDoSomething method where the exception occured. The next three are all CAB related (including the Infragistics line), then before that is essentially the call to Start().

So what happens is my policy causes the rethrow of the new exception, which gets thrown ‘back’ to OnExecuteAction in CAB code…which (currently) doesn’t have any PostSharp goodness to automatically wire up our exception handling policies. This means the exception will keep getting bubbled up the stack until it hits either a try/catch (that doesn’t rethrow) or an assembly with an exception aspect defined (PostSharp goodness). Let’s see what the call stack looks like after the new exception gets thrown.

callStack2

So it’s now Continuing execution from the next point that ‘handles’ the thrown exception. Problem is, that’s in the Start method and once execution continues beyond the call to base.Start then the application shutsdown (just the way a CAB app works).

Solution

Ok so I’ve gone away and thought about this for a bit and my solution is to change my policies. I now have a UI Layer Policy which never rethrows, it just logs and reports a message to the user. So all of my Modules and the main Shell use this Policy, there are other policies for other layers where required and an all purpose one that still does the log, wrap and rethrow…which eventually gets handled by some UI layer handler.

5. Lose Edit and Continue

I guess, due to the nature of how PS works (‘injecting code’, creating delegates etc Post compilation), you’ll see this kind of message popping up alot…

editAndContinue

when you try to edit code whilst debugging. So no more edit and continue if you add any Aspect Attributes to your class. What I’ve discovered so far is that if you have any methods, properties etc  in a class marked with an aspect attribute then you won’t be able to edit and continue anywhere in the class. If the class is ‘clean’ of aspects then you can edit and continue.

This is a heavy price to pay in my eyes, fine if your app is small and fast to start but my last app took 3 mins to build and compile so having to restart much more frequently when debugging would be very frustrating. Fortunately this problem is very easy to almost completely eliminate.

This straight from the documentation:

Disabling PostSharp

It can happen that you have an assembly referencing PostSharp.Public.dll, but that does not need to be processed by PostSharp. This is the case, for instance, when your assembly contains only aspects. Aspects don’t need to (and can not) be themselves transformed.

The easiest way to disable PostSharp in a project is to define the compilation symbol (aka constant) SkipPostSharp.

Therefore, it is possible to have a project with many build configurations and enable PostSharp in only some of these.

So what I’ve done is created a DebugWithPostSharp build configuration, which is a normal debug build. Then on the Debug configuration I added the SkipPostSharp symbol to the relevant projects. The Release configuration always gets PostSharp (really important because unit tests are run against the Release build).

Summary

There are so many useful ways you could use PostSharp, just make sure you take the time to thoroughly understand how it does it’s thing….experiment alot! This is just a few things I have learnt along the way, if I find anymore (and some spare time…) I’ll do a part 2.

Advertisements