Aug 092012
 
FacebookGoogle+StumbleUponLinkedInflattrPinterestReddittumblrTwitter

For general information about the Aspect Oriented Programming please refer to the earlier post: Aspect Oriented Programming (AOP) basics

In general, PostSharp offers a great deal of different types of predefined aspects that can be used and applied on methods, properties, events, fields, etc. The list below is directly taken from the PostSharp documentation.

  • TypeLevelAspect: Which is a base class for all aspects applied on types
  • OnExceptionAspect: Aspect that, when applied to a method, defines an exception handler around the whole method and calls a custom method in this exception handler.
  • MethodLevelAspect: Base class for all aspects applied on methods.
  • MethodInterceptionAspect: Aspect that, when applied on a method, intercepts invocations of this method.
  • MethodImplementationAspect: Aspect that, when applied on an abstract or extern method, creates an implementation for this method.
  • ManagedResourceIntroductionAspect: Aspect that, when applied to an assembly, adds a custom attribute to this assembly.
  • LocationLevelAspect: Base class for aspects defined in fields, properties, or parameters.
  • LocationInterceptionAspect: Aspect that, when applied on a location (field or property), intercepts invocations of the Get and Set semantics.
  • InstanceLevelAspect: Base class for aspects applied on types, but having the same lifetime as instances of the type to which they are applied.
  • FieldLevelAspect: Base class for all aspects applied on fields.
  • ExternalAspect: Aspect implemented in a different type, typically contained in an external assembly. Classes derived from PostSharp.Aspects.ExternalAspect must be annotated by the custom attribute PostSharp.Aspects.Configuration.ExternalAspectConfigurationAttribute.
  • EventLevelAspect: Base class for all aspects applied on events.
  • EventInterceptionAspect: Aspect that, when applied on an event, intercepts invocations of its semantics Add , Remove and Invoke
  • CustomAttributeIntroductionAspect: Aspect that, when applied to a target, adds a custom attribute to this target.
  • CompositionAspect: Aspect that, when applied on a type, introduces one or many new interfaces into that type.
  • AssemblyLevelAspect: Base class for all aspects applied on assemblies.

Method Level Aspect

In this post we are interested in implementing the logic and using an aspect that could be applied to methods. In order to implement it we need to create a class that will be derived from the OnMethodBoundaryAspect base class as defined by PostSharp.

By looking at the PostSharp documentation, this is how is the OnMethodBoundaryAspect class described:

Aspect that, when applied to a method defined in the current assembly, inserts a piece of code before and after the body of these methods.

The OnMethodBoundaryAspect base class offers several methods that could be overridden and each of them implements a specific piece of a puzzle that we are going to explain.

  • OnEntry: OnEntry method will be fired when the (underlying) method get first hit but no logic has been executed yet. OnEntry method is a perfect place where to implement the logic such as input parameters logging, caching, authentication/authorization, etc…
  • OnSuccess: Method executed after the body of methods to which this aspect is applied, but only when the method successfully returns (i.e. when no exception flies out the method.).
  • OnException: Method executed after the body of methods to which this aspect is applied, in case that the method resulted with an exception. This is a perfect place to log the error messages in an generic way and do something useful with that information.
  • OnExit: Method executed after the body of methods to which this aspect is applied, even when the method exists with an exception (this method is invoked from the finally block). This is a good place where to log the return value, inform other applications that the method has finished the execution, etc…

By implementing some of the above mentioned methods we will wire together the interception logic and the method itself.

As the PostSharp will recompile the code after the main compilation has been completed, this is how the code of the method to which we apply the aspect will look like in case we will override all of the above methods:

public void MyMethod()
{
    //1. On entry aspect call
    OnEntry(args);

    try
    {
        /*
         * method logic as originally written in the method.
         * This part remains untouched by postsharp.
         * */
        
        //2. OnSuccess aspect call
        OnSuccess(args);
    }
    catch (Exception ex)
    {
        //3. OnException aspect call
        OnException(args);
        throw;
    }
    finally
    {
       //4. OnExit aspect call.
       OnExit(args);
    }
}

Below is an example of an implemented aspect that is only useful for logging the Method Name and the Class where the method resides. Please notice that the parameter args contains full information about the declaring type and the method in context.

[Serializable]
public class LoggingAspect : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        Console.WriteLine(string.Format("OnEntry: {0}.{1}",
                args.Method.DeclaringType.Name, args.Method.Name));
    }

    public override void OnSuccess(MethodExecutionArgs args)
    {
        Console.WriteLine(string.Format("OnSuccess: {0}.{1}",
                args.Method.DeclaringType.Name, args.Method.Name));
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        Console.WriteLine(string.Format("OnExit: {0}.{1}",
                args.Method.DeclaringType.Name, args.Method.Name));
    }

    public override void OnException(MethodExecutionArgs args)
    {
        Console.WriteLine(string.Format("OnException: {0}.{1}",
                args.Method.DeclaringType.Name, args.Method.Name));
    }
}

Wire it up all together:

Install PostSharp

Obviously for this to work in your project you need to first install the PostSharp application that will install some plugins within the Visual Studio and more importantly install (or better update) some of the MSBuild targets so that there will be a “post compilation” step in order to include the aspect code directly in your methods. Yes, PostSharp uses, what is called, IL Weaving in order to include the aspect code in your application.
The installation procedure is really straightforward. You may download the installer from http://www.sharpcrafters.com/downloads

Add Reference to PostSharp.dll

Use the Add Reference dialog to make PostSharp a reference in your project.

Apply aspects to methods

Immagine to have such a class to which methods we are going to attach the LoggingAspect, as written above. Aapplying the [LoggingAspect] attribute at the method level we are binding together the method and the aspect implementation.

public class CustomerService
{
    private List<Customer> _customerList = new List<Customer>();

    [LoggingAspect]
    public Customer GetCustomer(string name)
    {
        return _customerList.FirstOrDefault
                (
                        t => t.FirstName.ToLower()
                        .Contains(name.ToLower())
                );
    }

    [LoggingAspect]
    public void AddCustomer(Customer c)
    {
        _customerList.Add(c);
    }
}

After the compilation, by inspecting the code with a .net decompiler (in my case JetBrains dotPeek) this is how the method will look like (decorating code has been removed for simplicity and for better understanding).

public void AddCustomer(Customer c)
{
    OnEntry(args);

    try
    {
        //method logic as originally written
        this._customerList.Add(c);

        OnSuccess(args);
    }
    catch (Exception ex)
    {
        OnException(args);
        throw;
    }
    finally
    {
       OnExit(args);
    }
}

Conclusion

PostSharp is a great tool by using which is really easy to apply the AOP techniques. I just scratched the surface with this post and obviously invite you to discover more examples and usages directly on the PostSharp web site.

I haven’t used the PostSharp in any of the live projects so far but I definitively think that is a great tool and that I will find a use case for using it as it could perfectly fit in the already written code, that’s it, code that has been already been written. This could perhaps be one of the next blog posts of mine of how can one implement and use PostSharp functionality in a non-green field project.

What I haven’t described in this post is how to use CompileTimeInitialize, RuntimeInitialize and SetAspectConfiguration methods that will offer us a great deal of customization and control of how the aspect will be configured at compile or runtime itself.

Read Next

References

zoran maksimovic
About the author:
My name is Zoran Maksimovic. I'm a passionate programmer and interested in everything about Software Development, Object-Oriented Design and Software Architecture. Feel free to contact me or to know more about me in the about section.
FacebookGoogle+StumbleUponLinkedInflattrPinterestReddittumblrTwitter

Leave a Reply