So I hope you downloaded Post Sharp and installed it. Heres a small application that shows a tiny little bit of caching. It’s the simplest factorial algorithm.
Here’s the basic program. You´ll need to reference both PostSharp.Laos and PostSharp.Public assemblies.
{
static void Main(string[] args)
{
Console.WriteLine(Factorial(20));
Console.WriteLine(Factorial(10));
Console.WriteLine(Factorial(15));
Console.ReadLine();
}
public static ulong Factorial(ulong val)
{
Console.WriteLine("Calculating Factorial of " + val.ToString());
return val <= 1 ? val : val * Factorial(val - 1);
}
}
What that code does? It just calculates the factorial of a given number recursively. Not much to say here. It prints out the current factorial that’s being calculated. In a real world, you wouldn’t need that, but in our example it’s needed so you believe (and can see with your own eyes) that our simple caching will work.
The important stuff is down bellow. It’s the aspect that will do the caching for us:
class Cache : OnMethodBoundaryAspect
{
private volatile Dictionary<ulong, ulong> internalCache;
public Cache()
{
internalCache = new Dictionary<ulong, ulong>();
}
//called when entering a marked method
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
//use the parameter as key to cache
ulong key = (ulong)eventArgs.GetReadOnlyArgumentArray()[0];
ulong cachedValue;
//marks the method execution with the key, so there's no need to access the ArgumentArray later.
eventArgs.MethodExecutionTag = key;
//try to fetch information from cache
if (internalCache.TryGetValue(key, out cachedValue))
{
//if information is found, then return that.
eventArgs.ReturnValue = cachedValue;
eventArgs.FlowBehavior = FlowBehavior.Return;
}
}
public override void OnSuccess(MethodExecutionEventArgs eventArgs)
{
//uses the previously assigned key to cache the return value
ulong key = (ulong)eventArgs.MethodExecutionTag;
internalCache.Add(key, (ulong)eventArgs.ReturnValue);
}
}
The Constructor is there to create the new instance of our cache. Acctually it´s a Dictionary, I know that.
OnEntry is called whenever a method you apply that aspect to is called. We’re gonna apply that to the Factorial soon. If you look at the code, will see that it only uses the parameter as a key to our cache, add the key as a tag (so we don’t need to access the ArgumentArray again) asks the cache if that key was inserted. If the cache finds the key, we use the value associated with it as a return value and tell our aspect to return.
OnSuccess is called whenever a method successfully exits. What’s successfully? That’s when no exception is thrown. So, if everything goes well this method will be called and we´ll be able to use the tag inserted by OnEntry and add the return value to our cache.
All this methods are inherited from OnMethodBoundaryAspect provided by PostSharp.Laos. If you installed and opened one of their examples you know all that. (;
Ok, so now we have the method we want to cache and the aspect that will work as a cache. How do we wire the together? Here´s the beauty of PostSharp. You can just add and attribute to the Factorial method. OK, all right… Which attribute? [Cache]. Your aspect name. Now your Factorial method should look something like this:
[Cache]
public static ulong Factorial(ulong val)
{
Console.WriteLine("Calculating Factorial of " + val.ToString());
return val <= 1 ? val : val * Factorial(val - 1);
}
}
Now, if you tested the factorial without the cache attribute you might remember that it printed out a lot of lines: 20 + 10 + 15 (one for each time the factorial function is called) + 3 (one for each result). Now, add the cache attribute and run it. You´ll have 20 + 3 (one for each result).
Remember, you can’t cache information you don’t have, so theres no way to not print the first 20 lines.
All right, that’s all for today. Next we’ll create a nice caching mechanism to use with .netTiers generated methods, using Enterprise Library Caching Application Block.











