Search code examples
c#.netmemorycache

Getting custom CacheItems from MemoryCache


I'm implementing a MemoryCache with a derived CacheItem, but having difficulty interacting with it once it's in the cache. For example:

class Program
{
    static void Main(string[] args)
    {
        MemoryCache cache = MemoryCache.Default;
        CacheItemPolicy policy = new CacheItemPolicy();
        CustomCacheItem someItem = (CustomCacheItem)cache.AddOrGetExisting(new CustomCacheItem(1, "tacos", "waffles"), policy);

        Console.ReadLine();
    }
}

public class CustomCacheItem : CacheItem
{
    public int FailureCt { get; set; }

    public CustomCacheItem(int _failureCt, string _key, string _value)
        : base(_key, _value)
    {
        FailureCt = _failureCt;
    }
}

This throws an error of Unable to cast object of type 'System.Runtime.Caching.CacheItem' to type 'CacheTest.CustomCacheItem'. which sort of makes sense; maybe it doesn't retain the information about the cache item put in. But if so, how do I get my custom cache item out? How do I interact with that property (in this case FailureCt) if the return value is of the generic base type?


Solution

  • The reason is that MemoryCache.AddOrGetExisting(CacheItem, CacheItemPolicy) is creating a new CacheItem internally:

    public override CacheItem AddOrGetExisting(CacheItem item, CacheItemPolicy policy)
    {
        if (item == null)
            throw new ArgumentNullException("item");
        return new CacheItem(item.Key, AddOrGetExistingInternal(item.Key, item.Value, policy));
    }
    

    MemoryCache source code


    I'd recommend storing FailureCt in the value itself and not in the CacheItem wrapper:

    public class CacheValue
    {
        public int FailureCt { get; set; }
        public string Value { get; set; }
    }
    

    And then:

    CacheValue someItem = (CacheValue)cache.AddOrGetExisting("tacos", new CacheValue()
    {
        FailureCt = 1,
        Value = "waffles"
    }, policy);