posts - 94, comments - 124, trackbacks - 82

My Links

News

View Anthony Trudeau's profile on LinkedIn

Add to Technorati Favorites

Article Categories

Archives

Post Categories

Image Galleries

Other Links

Tuesday, February 24, 2009

Simple Caching

In a current project I had a need for a lightweight caching mechanism.  My needs were driven by a desire to minimize file access.  The file in question would likely not be too long; however, I couldn't guarantee that.  Therefore, a caching framework such as provided by the Enterprise Library was just too much.  This post talks about what I put together.  The following are the only imports necessary.

using System;

using System.Collections.Generic;

 

My requirements are simple enough.  I want to be able to add an object to a cache based on a string name.  I want to be able to retrieve that same object, and I want to be able to determine (without raising an exception) if the cache contains an object.  And I want to be able to clear the cache.  I will clear the cache if I determine that my file has changed -- thus likely invalidating data within the cache.  Of course I want it strongly typed and to support any type of object (for future use)  and finally it needs to be thread safe.  Here's the pseudo-code interface:

void Add(string key, T newObject)
T GetObject(string key)
void Clear()
bool IsCached(string key)

All of these requirements are simple to implement.  But, I decided that I would add support for one more thing -- ICloneable.  The support wouldn't be an interface implementation, but rather supporting the caching of objects that implement the interface.  This can be important, because the objects I deal with are mutable and I don't want external code to corrupt my object state.

Here's the completed class that does everything I need.

 

internal class ObjectCache<T>

{

    private Dictionary<string, T> _cache = new Dictionary<string, T>();

    private object _syncObject = new object();

 

 

    public ObjectCache()

    {

    }

 

    public void Add(string key, T newObject)

    {

        if (string.IsNullOrEmpty(key))

            throw new ArgumentNullException("key");

        if (newObject == null)

            throw new ArgumentNullException("newObject");

 

        /* create a clone copy for the cache if the object implements
         * ICloneable; this provides an
immutable collection of cached objects */

        T cacheObject = (newObject is ICloneable
                        ? (T)((ICloneable)newObject).Clone() : newObject);

 

        lock (_syncObject)

            _cache.Add(key, cacheObject);

    }

 

 

    public T GetObject(string key)

    {

        T cacheObject;

 

        lock (_syncObject)

            cacheObject = _cache[key];

 

        /* return a copy of the cached object to enforce the

         * immutable collection */

        return (cacheObject is ICloneable
               ? (T)((ICloneable)cacheObject).Clone() : cacheObject);

    }

 

 

    public void Clear()

    {

        lock (_syncObject)

           _cache.Clear();

    }

 

 

    public bool IsCached(string key)

    {

        lock (_syncObject)

            return _cache.ContainsKey(key);

    }

}

posted @ Tuesday, February 24, 2009 11:08 AM | Feedback (2) | Filed Under [ .NET ]

Powered by: