Archive

Download demo project source code

Yesterday we went over creating an aspect and applying it to a method. PostSharp is flexible in how aspects can be applied which results in outstanding benefits for us as developers. Imagine our exception wrapper aspect automatically being applied to any new method that is added to any class in the project. What about logging exceptions? No longer do we have to remember to add exception logging code to new methods. Of course, the practical applications are far beyond these simple scenarios but it gives you an idea of the power of PostSharp.

OnExceptionAspect is intended to work with methods. Yesterday we applied our aspect to the target method directly, which did the job but

  • What happens when we need to profile multiple methods?
  • What happens when we want to profile every method in every class?

That's a lot of work if we were to manually apply the aspect to each method.

OnMethodBoundaryAspect

PostSharp comes with another aspect that we can use called OnMethodBoundaryAspect. This class allows us to intercept certain points in a method’s execution by providing 4 virtual methods we can override

  • OnEntry - Before the execution of the method body
  • OnExit - Always called when a method is done executing even if there was an error
  • OnSuccess - Called only when a method is done executing and there were no exceptions
  • OnException - Called only when a method has stopped executing due to an unhandled exception

To give a clear understanding of multicasting, we’ll build a simple tracing aspect that will log the entry and exit of a method as it’s executed. Add a new file called MethodTraceAspect.cs and add the following code

[Serializable]
public class MethodTraceAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Debug.WriteLine(args.Method.Name + " started");
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Debug.WriteLine(args.Method.Name + " finished");
    }
}

This aspect is the, “Hello World” of Aspect Oriented Programming, but it serves our purpose for today. When applied to a method this aspect will write ‘Started’ and ‘Finished’ to the output window. Go ahead and apply it to the GetByName method in InMemoryDataStore.cs file

[DatabaseExceptionWrapper]
[MethodTraceAspect]
public IQueryable GetByName(string value)
{
    var res = _contactStore.Where(c => c.FirstName.Contains(value) 
                    || c.LastName.Contains(value));

    if (res.Count() < 1)
    {
        ThrowNoResultsException();
    }

    Thread.Sleep(3000);
    return res.AsQueryable();
}

Run the application and do a search. As expected you see

GetByName started
GetByName finished

In the output window.

Class Level Declaration

Instead of applying the aspect manually to every method, we can apply the aspect only once, on the class. PostSharp will automatically apply the aspect to all methods in the class. Let's try it. Remove the [MethodTraceAspect] from GetByName method and apply to the InMemoryDataStore class

[MethodTraceAspect]
internal class InMemoryDataStore : PostSharpDemo1.IContactRepository
{
    …
}

When we run the application there is a lot more being displayed in the output window, just by starting the application.

.cctor Started
InitializeData Started
set__contactStore Started
set__contactStore Finished
get__contactStore Started
get__contactStore Finished
get__contactStore Started
get__contactStore Finished
get__contactStore Started
get__contactStore Finished
get__contactStore Started
get__contactStore Finished
get__contactStore Started
get__contactStore Finished
get__contactStore Started
get__contactStore Finished
InitializeData Finished
.cctor Finished
.ctor Started
.ctor Finished
GetAll Started
get__contactStore Started
get__contactStore Finished
GetAll Finished

Notice that there are calls to methods not in the class. Remember that property getters and setters are turned into methods when your code is compiled which makes them eligible for receiving the aspect. The .cctor entry is the static constructor and .ctor is the instance constructor.

As interesting as this is, you won’t always want to have the aspect applied to absolutely everything. There are a few ways to avoid aspect application on a specific target. We'll cover those tomorrow.

Conclusion

Today we saw another aspect we can take advantage of and we also saw how we can use multicasting to apply an aspect to multiple targets with one line of code. Tomorrow we’ll look at even more multicasting.

 

self[5]Dustin Davis is an enterprise solutions developer and regularly speaks at user groups and code camps. He can be followed on twitter @PrgrmrsUnlmtd or his blog Programmers-Unlimited.com

Download demo project source code

Welcome to day 1 of learning PostSharp. This series will walk you through the features of PostSharp over the course of a few weeks. Each feature will be explored and used in a functioning project to give a better understanding of the examples.

This week we'll be using PostSharp to enhance a simple contact management application while giving you an introduction to some of the out-of-the-box aspect classes that PostSharp provides for us.

Getting started

You will need to download and install PostSharp and the demo project source code. For this series we will be using PostSharp 2.0.9.3.

About the demo application

The demo application is a simple windows forms project that uses an in-memory data store. It features search, add, edit and delete functionality. Go ahead and run the application and play around with it.

The Problem

If you have not done so already, try doing a search for a name that isn’t in the list. You receive an error dialog. This exception is very cryptic and contains some sensitive information about the data layer.

Exceptions are great for debugging because they contain a lot of information that can be used to track down troublesome code and conditions. However, this can be a double edged sword. If you were exposing a web service or a web site to the public and exception data was allowed to bubble up to the user, it could be used for malicious purposes. Another case is that the end user doesn’t need to know very specific details about what happened, just that something went wrong.

The best practice in these cases are to capture the real exception, perform some actions on it (such as logging) and then throw a new, more generic exception.

The Fix

There are two places where we can handle this, the data layer and the UI. We want to handle it in the data layer. The reason why is because we don’t want to expose details to the other layers if we don’t have to. This point might seem lost on this simple demo, but in real world development, you might have many public consumers of a data layer so you have to consider what data is exposed.

Update the GetByName method in InMemoryDataStore.cs by adding a try/catch around the method body

public IQueryable GetByName(string value)
{
    try
    {
        var res = _contactStore.Where(c => c.FirstName.Contains(value) 
                    || c.LastName.Contains(value));

        if (res.Count() < 1)
        {
            ThrowNoResultsException();
        }

        Thread.Sleep(3000);
        return res.AsQueryable();
    }
    catch (Exception ex)
    {
        //Log exception here
        throw new Exception("There was a problem.");
    }
}

Run the application and try a search for a non-existent name. This time we get a dialog with a friendly message and none of the sensitive information.

A Better Way

Not only did we fix our problem, we also cluttered the method with at least 7 lines of code to do it and it isn’t reusable. If we wanted to apply the same fix to the rest of the methods we would need to add the same try/catch to each method.

Since this problem is a cross-cutting concern we can employ Aspect Oriented Programming. This is where PostSharp comes in.

OnExceptionAspect

PostSharp comes with an aspect class called OnExceptionAspect that is specifically designed for implementing exception handling policies. This is exactly what we need. Add a new file named DatabaseExceptionWrapper.cs and add the following code

[Serializable]
public class DatabaseExceptionWrapper : OnExceptionAspect
{
    public override void OnException(MethodExecutionArgs args)
    {
        string msg = string.Format("{0} had an error @ {1}: {2}\n{3}", 
            args.Method.Name, DateTime.Now, 
            args.Exception.Message, args.Exception.StackTrace);

        Trace.WriteLine(msg);

        throw new Exception("There was a problem");
    } 
}

To use OnExceptionAspect, we simply inherit from it. OnExceptionAspect exposes a few virtual methods that we can override to gain access to certain events. Since we want to handle exceptions when they occur, we override the OnException method.

The OnException method is called when an unhandled exception occurs in the target method. PostSharp will wrap the target method in a try/catch where the code we provided will be placed in the catch.

Inside OnException, we build a string to hold some exception information that we will log. OnException provides us with a MethodExecutionArgs parameter that contains useful information about the current method and the exception that was thrown. args.Exception holds the exception that was thrown by the method so we can extract the details we need from there. We’ll cover more of MethodExecutionArgs later this week.

Applying an aspect

Now that we have it, we need to use it. PostSharp is flexible in how aspects can be applied. Today we'll go over the most direct way which is applying it to the target method declaration. Open the InMemoryDataStore.cs and navigate to the GetByName method. Remove the extra code we added before and add a [DatabaseExceptionWrapper] attribute to the method declaration.

[DatabaseExceptionWrapper]
public IQueryable GetByName(string value)
{
    var res = _contactStore.Where(c => c.FirstName.Contains(value) 
                || c.LastName.Contains(value));

    if (res.Count() < 1)
    {
        ThrowNoResultsException();
    }

    Thread.Sleep(3000);
    return res.AsQueryable();
}

Run the application again and the result is exactly the same as it was before. The difference is that we now have a reusable and clean way to apply our exception wrapping solution to methods.

Since PostSharp is a Post-Compile processor, meaning it does its work after msbuild.exe has turned your C# into MSIL, it uses the attributes to determine the work that needs to be done. PostSharp will find the DatabaseExceptionWrapper attribute decoration on the GetByName method and then inject our code in the correct spots.

GetExceptionType

Another method that OnExceptionAspect exposes for us is GetExceptionType. The way OnExceptionAspect works is by wrapping the method in a try/catch block and catching exceptions of type Exception. But there will be cases when you want to handle a specific type of error.

A good example of this would be a connection time-out exception when making a call to a web service. Your exception handling policy for a connection time-out could be to wait and retry before giving up. But you only want to handle that specific exception, not all exceptions. This is where GetExecutionType comes in.

Implementing GetExceptionType is nothing more than returning the type you wish to handle. This method is called at build-time by PostSharp to determine how the try/catch block is going to be created.

Add the following code to our aspect class

public override Type GetExceptionType(System.Reflection.MethodBase targetMethod)
{
    return typeof(InvalidOperationException);
}

GetExceptionType is called at compile time by PostSharp to determine how to generate the try/catch. We’re telling PostSharp that it should build the catch clause to only handle InvalidOperationException types. If a different exception were thrown then our aspect would not cover it.

To add flexibility, you can declare an ExceptionType public property on the aspect that will allow the type to be set when the aspect is declared. The GetExceptionType method would only need to return that property.

Conclusion

How much time will you save by creating logging code once and then forgetting about it? Adding logging and exception handling to new and existing methods is now just one line of code and no clutter. Different aspects can be built to handle different scenarios and can be added and removed to any method in any combination with little or no development effort.

 

selfDustin Davis is an enterprise solutions developer and regularly speaks at user groups and code camps. He can be followed on twitter @PrgrmrsUnlmtd or his blog Programmers-Unlimited.com

CarlandRichard

For those of you who don’t yet subscribe to .NET Rocks! and its training video counterpart, dnrTV, you’re missing out on some wonderfully entertaining and informative talk shows.

Since 2002, Carl Franklin and Richard Campbell have been speaking with guests about programming in Microsoft .NET and, after nearly 650 episodes, show no signs of slowing down.

Gael was invited to be on .NET Rocks! in early February but, due to a bad phone line, he had to reschedule. Luckily both he and Carl attended this year’s NYC Code Camp, where they could finally sit down and record face-to-face. Or so he thought…

Listen to the first few minutes of the podcast to learn how Carl and Richard were finally able to record the show with Gael. Then, after you’ve had a good chuckle, continue listening to the podcast to learn more about programming with aspects.

DotNet Rocks

Listen to the podcast: http://www.dotnetrocks.com/default.aspx?showNum=640

Highlights include:

10:32 – What is an aspect?

12:10 – Using PostSharp for more than just Tracing and Logging

14:12 – Why having a bug in your aspect is safer than in the implementation of the manual line

20:20 – Two multithreading issues that can be solved using aspects

25:41 – Richard’s favorite example of AOP

36:43 – Static versus Dynamic AOP

40:08 – What’s next for PostSharp

Show the Code.

Gael also recorded a PostSharp demonstration with Carl on dnrTV. The shows on dnrTV are equally as entertaining as those on .NET Rocks! but with one very important difference: the code!

In this webcast-like format, guests are able to demonstrate technical topics in greater detail. That’s exactly what you’ll see in the recording with Gael as he dives deep into PostSharp – showing both common and advanced aspect usage.

dnrtv2

Watch the recording:  http://dnrtv.com/dnrtvplayer/player.aspx?ShowNum=0190

Highlights include:

02:10 – TraceArgumentsAspect : OnExceptionAspect

13:47 – TracePerformanceAspect : OnMethodBoundaryAspect

23:15 – CacheAttribute : MethodInterceptionAspect

45:57 – Undo/Redo

Special thanks to Carl and Richard for inviting Gael as a guest on both shows. And many thanks to all of you who watched the shows and provided feedback. Keep it coming.

Happy PostSharping!

-Britt