Source

CacheGen /

Filename Size Date modified Message
CacheGen
CacheGen.Tests
33 B
1.7 KB
3.4 KB

Introduction

This is a T4 template and library to make caching awesome and pain free! This is accomplished by utilizing the code-generation abilities of T4 to write the really hard and tedious code for you. This leaves you with a static class, which passes through to a chosen CacheMechanism, with the correct type. Finally! No more manual casting, remembering what the caching options should be, nor what the magic string is.

Example

Let's say you want to cache blog posts and the generated HTML for some high traffic page in our ASP.Net website

First, you'd do something like this in the T4 template:

var gen=new CacheGenerator("MyCache", "new ASPCacheMechanism()"); //use ASP.Net's caching mechanism(built in)
gen.Namespace="Earlz.CacheGen.Examples"; //set the namespace to whatever you like
gen.AddItem(new CacheObject{Name="HighTrafficPage", Type="string"}); //add our high traffic page cache
gen.AddItem(new CacheObject{Name="BlogPosts", KeyType="int", ValueType="BlogPost"}); //add our BlogPosts cache with a key type of int and value type of BlogPost
Write(gen.ToString()); //write it out to generated C# file

From there, it's magically very easy to use the cache

BlogPost mypost=MyCache.BlogPosts[some_id]; //no casting! 
string somepage=MyCache.HighTrafficPage; 
//a super easy pattern to load the cache if it doesn't exist
var post= MyCache.BlogPosts[id] ?? MyCache.BlogPosts[id]=LoadPost(id);

ICacheDictionary

There are currently two options for the CacheDictionary. Which one wokrs best for you will depend on your use case:

  • TrackingCacheDictionary
  • UntrackedCacheDictionary

The untracked version is the default and I'll discuss it first. Basically, it relies on a .ToString implementation for the key type which is unique, but not random. If you use this version, you must make sure that for two identical key objects (or identical enough for your needs) the .ToString() method will return the same string. And that if two key objects are clearly not identical, they must return a different result from .ToString(). Despite these requirements, this untracked dictionary is the fastest and most performant of the two. It passes almost directly through to the CacheMechanism. There are never any locks.

The tracked version on the other hand is nice when you need to use a key type which you can't modify. For instance, if a library provides a "Widget" and you want to use that as a key, but it's ToString() does not meet the above requirements(note, it DOES require that it's .Equals method works appropriately though), then the tracked dictionary is for you.

There are many downsides to the tracking though. For one, it's much more complex. Complexity in concurrent code spells trouble. I've tested it and had it reviewed by a second pair of eyes, but there could always be that one stray race condition that I didn't catch. Also, the tracking requires a few locks and it can possibly break if you have a LOT of different keys which will seldom be acessed. Tracking a very large number of keys might make you hit the maximum object size limit, as well as possibly leaking memory. I recommend only using it if you really have to.

CacheMechanism

This is an extremely simple to implement interface to your caching method. Basically, nulls can not be cacheable is the only strict requirement. If a value is passed in as null, then the value associated with the passed in key should be removed from the cache. Also, these methods MUST be thread-safe.

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.