In many cases, using a caching mechanism can drastically improve performances. Processed results of methods can be stored in memory or in files so they are ready to be returned immediately when we call the methods again.
In some .NET applications, we can use the MemoryCache class from System.Runtime.Caching to store data in memory. However, using such library in a basic way may induce some problems such as:
- Adding caching in each method which needs it may result in less readable and polluted code.
- The repetitive use of such code may induce errors (especially copy-pasted code).
- Depending on the nature of projects (mobile apps, websites, web services, desktop apps), we may need a different caching approach.
In order to avoid all these problems, I have written a generic caching aspect using Autofac and Castle DynamicProxy.
Caching the result of a method is as simple as the following code:
Here, we call the method many times but before the last call we do a 2 seconds break:
As expected, the three first calls returned the same Guid instead of three different because the first call result were cached for one second. After the two seconds break, another result were processed for the last call as the first value has expired.
Implementing the caching aspect
First, we have to create a caching abstraction using an interface. Depending on the project’s nature, the implementation will be different. In my case, I will use the MemoryCache default singleton which is good for desktop applications:
Secondly, we have to create the CacheResult attribute:
In a third time, we need to implement the class that will intercept the methods decorated with the CacheResult attribute. For each method call, we will compute a unique key based on the class name, the method name and the parameters. If the result exists in the cache provider, we will return it as is. Otherwise, the method will be executed and the result will be stored in the cache with the specified duration in milliseconds:
Finally, we need to wire all these classes with an Autofac module: