How to solidify your application's code using PostSharp

Take advantage of PostSharp's compile-time weaving features to reduce code clutter and solidify your application’s code

PostSharp

PostSharp

AOP (Aspect Oriented Programming) is a programming paradigm that compliments OOP (Object Oriented Programming) in that it focusses on code reuse so as to reduce code clutter in your application. Contrary to OOP, you can take advantage of AOP to inject the reusable implementations in any method in your application. In essence, AOP complements OOP by providing you another way to achieve modularity and also reduce code clutter.

You can leverage AOP to implement the nonfunctional requirements (Exception Handling, Caching, Logging, Execution Timing, Security, Transaction Management, etc.) easily in your application. Aspect-oriented programming isolates the concerns of your application, reduces code clutter, and improves the maintainability and readability of your application's code.

AOP can be leveraged to remove intermingled code, write cleaner code, increase code abstraction and modularity, reduce maintenance and development costs, and make applications more manageable and flexible.

PostSharp is one of the most popular AOP frameworks around that can be used to implement AOP in applications. PostSharp inspects the compiled IL code and then it attaches actions to the body of the method on which a particular aspect has been defined using one or more attributes. This article is a continuation on the series of articles on PostSharp.

Implementing a logging aspect using PostSharp

An aspect in AOP is defined as the modularization of a concern. In this section we will learn how we can implement a logging aspect to log data relevant to a method (method execution information that may even include the exception details) into a log store. Let’s assume for the sake of simplicity that the log store or the log target is a text file. I would like to use the file logger class that we implemented in an earlier post here.

The following code listing shows how you can build your custom logging aspect using Postsharp.

[Serializable]

public class LoggingAspect : OnMethodBoundaryAspect

    {

        static readonly FileLogger logger = new FileLogger();

        public override void OnEntry(MethodExecutionArgs args)

        {

            logger.Log("Method name: "+args.Method.Name);

            logger.Log("DeclaringType name: " + args.Method.DeclaringType.Name);

        } 

        public override void OnExit(MethodExecutionArgs args)

        {

            //Write your implementation here           

        }

        public override void OnException(MethodExecutionArgs args)

        {

            logger.Log("Exception: "+ args.Exception);

            args.FlowBehavior = FlowBehavior.Continue;

        }

    }

Note how the LoggingAspect class extends the OnMethodBoundaryAspect class and implements the OnEntry, OnExit and OnException overridable methods.

The following code snippet illustrates how you can use the logging aspect we just implemented.

static void Main(string[] args)

        {

            TestLoggingAspect();

            Console.ReadLine();

        }

        [LoggingAspect]       

        public static void TestLoggingAspect()

        {

            throw new Exception("This is a test message");

        }

And, we are done! We have created a logging aspect using PostSharp and learnt to use it in our code.

Implementing a caching aspect using PostSharp

Now that we know how to create custom aspects and then apply them as attributes in our application, let’s now explore how we can build a custom caching aspect using PostSharp. To build your own custom caching aspect you may create a custom class that extends the MethodInterceptionAspect class and overrides the OnInvoke method. The following code snippet illustrates this.

[Serializable]

    public class CachingAspect : OnMethodBoundaryAspect

    {

        public override void OnInvoke(MethodInterceptionArgs args)

        {

            // Write your code here

        }

    }

Let's now modify the CachingAspect class to include a constructor so that we may pass the key of the objects that are to be stored or retrieved to and from the cache. Here’s how the updated CachingAspect class would look like now.

[Serializable]

    public class CachingAspect : MethodInterceptionAspect

    {

        private readonly string key;

        public CachingAspect(string key)

        {

            this.key = key;

        }

      //Other methods

    }

You would now want to search for data based on the key passed to the constructor of the CachingAspect class. If data is not available in the cache, then the data should be added to the cache. If data is available, the same should be returned. Assuming that you have a class named CacheManager to store and retrieve data to and from the cache, the following code listing shows how you can implement all this using the OnInvoke method.

[Serializable]

    public class CachingAspect : MethodInterceptionAspect

    {

        private readonly string key;

        public CachingAspect(string key)

        {

            this.key = key;

        }

        public override void OnInvoke(MethodInterceptionArgs args)

        {

            object value = CacheManager.Get(key);

            if (value == null)

                CacheManager.Add(value, key);

            args.ReturnValue = value;

            base.OnInvoke(args);

        }

    }

You can now apply this CachingAspect to your application as and when you need to cache data.

This article is published as part of the IDG Contributor Network. Want to Join?

From CIO: 8 Free Online Courses to Grow Your Tech Skills
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.