Exploring ShadeTree Features, Part 2: Cache


Or, as I like to call it: “That stupid dictionary thing we’ve all written a thousand times but were too lazy to component-ize for reuse”

How many times have you written code like this in your C# 2.0-and-later life?

Foo foo = null;

if( ! fooCache.TryGetValue(key, out foo))
{
    foo = new Foo();
    fooCache.Add(foo.Key, foo);
}

return foo

Well, no more!  Enter ShadeTree.Core.Cache!

Nifty features:

  1. Automatic cache miss value creation: When you attempt to get an item from the cache that’s not there, if configured to do so, it’ll new one up for you, add it, and return it.
  2. Quiet Add: Call the Store method to add an item if it’s not already added (otherwise, it’ll do nothing)
  3. Quiet Remove: Remove won’t throw an error if the item isn’t in the Cache
  4. Each(): Handy lambda-friendly version of ‘for each’
  5. Exists(): Handy lambda-friendly version of TryGetValue

Cache Miss Handling Example

This one I particularly like, especially when you need something like this: Dictionary<string, IList>.

Consider this example: We want to have a Cache<string, IList>.  We want to add a new key "Blah" and add a new Foo to it’s list.

With Dictionary<T,U>, you have to do something like:

Dictionary<string, IList<Foo>> dict = new Dictionary<string, IList<Foo>>();

IList<Foo> fooList = null;

if( ! dict.ContainsKey("Blah") )
{
    fooList = new List<Foo>();
    dict.Add("Blah", fooList);
}

fooList.Add(new Foo());

But with Cache, it’s much simpler:

Cache<string, IList<Foo>> cache = new Cache<string, IList<Foo>>(k => new List<Foo>());
cache.Get("Blah").Add(new Foo());

The trick is that little lambda expression (k => new List()).  When the call to Get("Blah") fails to find anything in the underlying dictionary, it’ll add a new entry to the dictionary with key "Blah" and the result of that lambda expression (i.e. a new List).

Exploring ShadeTree Features, Part 1: Static Reflection with ReflectionHelper