views:

114

answers:

3

I've created a generic wrapper for using the Cache object:

public class Cache<T> where T : class
{
    public Cache Cache {get;set;}
    public CachedKeys Key {get;set;}

    public Cache(Cache cache, CachedKeys key){
        Cache = cache;
        Key = key;
    }

    public void AddToCache(T obj){
        Cache.Add(Key.ToString(),
            obj,
            null,
            DateTime.Now.AddMinutes(5),
            System.Web.Caching.Cache.NoSlidingExpiration,
            System.Web.Caching.CacheItemPriority.Normal,
            null);                   
    }

    public bool TryGetFromCache(out T cachedData) {
        cachedData = Cache[Key.ToString()] as T;
        return cachedData != null;
    }

    public void RemoveFromCache() {
        Cache.Remove(Key.ToString()); }
}

The CachedKeys enumeration is just a list of keys that can be used to cache data.

The trouble is, to call it is quite convuluted:

var cache = new Cache<MyObject>(Page.Cache, CachedKeys.MyKey);
MyObject myObject = null;

if(!cache.TryGetFromCache(out myObject)){
    //get data...
    cache.AddToCache(data); //add to cache
    return data;
}

return myObject;

I only store one instance of each of my objects in the cache.

Therefore, is there any way that I can create an extension method that accepts the type of object to Cache and uses (via Reflection) its Name as the cache key?

public static Cache<T> GetCache(this Cache cache, Type cacheType){
        Cache<cacheType> Cache = new Cache<cacheType>(cache, cacheType.Name);
    }

Of course, there's two errors here:

  • Extension methods must be defined in a non-generic static class
  • The type or namespace name 'cacheType' could not be found

This is clearly not the right approach but I thought I'd show my working. Could somebody guide me in the right direction?

+1  A: 

How about:

public static Cache<T> GetCache<T>(this Cache cache)
{
    return new Cache<T>(cache, typeof(T).Name);
}

This will of course have to be defined in another class.

ErikHeemskerk
That's basically what I already have in my `Cache` constructor (apart from using the `Name` property as a key, which is a bit of an after-thought).
David Neale
But it does what you want, doesn't it?
ErikHeemskerk
Yes true, I hadn't thought of simply making a generic method instead of a generic class. I've ended up simply adding generic extension methods to achieve the functionality now.
David Neale
A: 

I ended up using generic extension methods:

public static class CacheExtensions
{
    public static void Remove<T>(this Cache cache) where T : class
    {
        cache.Remove(typeof(T).Name);
    }

    public static void AddToCache<T>(this Cache cache, object item) where T : class
    {
        T outItem = null;
        if (cache.TryGetItemFromCache<T>(out outItem))
            throw new ArgumentException("This item is already in the cache");

        cache.Insert(typeof(T).Name,
                item,
                null,
                DateTime.Now.AddMinutes(5),
                System.Web.Caching.Cache.NoSlidingExpiration,
                System.Web.Caching.CacheItemPriority.Normal,
                null);
    }

    public static bool TryGetItemFromCache<T>(this Cache cache, out T item) where T : class
    {
         item = cache.Get(typeof(T).Name) as T;
         return item != null;
    }
}

Called like:

MyObject myObject = null;
if(!Cache.TryGetItemFromCache(out myObject)){
     //get data
     Cache.AddToCache<MyObject>(data);
}

and..

Cache.Remove<MyObject>();
David Neale
A: 

I think the following method needs to be changed:

 public static bool TryGetItemFromCache<T>(this Cache cache, out T item) where T : class
    {
         item = cache.Get(typeof(T).Name) as T;
         return item != null;
    }

If the item is not in the cache don't you want to put the item in the cache for later use or later retrieval.

Thanks,

azamsharp
That will be handled in the calling code. The `Cache` has no knowledge of where the data is coming from.
David Neale