正确使用MemoryCache和泛型?

时间:2018-03-15 21:20:01

标签: c# generics value-type reference-type memorycache

我希望使用System.Runtime.Caching.MemoryCache,但我想知道如何将它与泛型一起使用。

在以下示例中,如果T是值类型,我将遇到麻烦。

public T GetItem<T>(string key, Func<T> loadItemFromDb)
{
    var cachedItem = (T) memoryCache.Get(key);
    if(cachedItem != null)
       return cachedItem;

    // call db
    //put result in cache
    // return result
}
如果MemoryCache.Get(string key)标识的缓存条目不存在,则{p> null会返回key,并且会在NullReferenceException尝试(T)null时引发T T值类型)

我怎样才能为每个where T : class获得类似的行为?

编辑:我删除了@Dao public abstract class EntityDao implements Base { @Override @Query("SELECT * FROM " + Entity.TABLE_NAME) public abstract Flowable<List<Entity>> getEntities(); } interface Base { Flowable<List<Entity>> getEntities(); } ,因为此约束阻止了我正在描述的情况。

编辑2:我添加一些代码来提供意图

2 个答案:

答案 0 :(得分:4)

问题是如果值为null,则强制转换可能会失败。所以如果值为null则不会强制转换

public T GetItem<T>(string key, Func<T> loadItemFromDb)
{
    object cachedItem = memoryCache.Get(key);
    if (cachedItem is T)
       return (T)cachedItem;
    T item = loadItemFromDb();
    memoryCache.Add(key, item, somePolicy);
    return item;
}

这里的价值类型没有问题;如果T是值类型,并且cachedItem不是框T,那么我们绝不会将cachedItem转换为T

在C#7的FYI,您可以将其收紧一点:

    if (cachedItem is T t)
       return t;

现在根本没有演员阵容!

答案 1 :(得分:0)

根据@ ericlippart的回答,这看起来像是一种很好的方法来实现作为扩展方法,并且在他的回答中没有解决几个问题:

  1. 您需要一个缓存策略,以便在未传递给函数的问题中插入loadItemFromDb函数的结果。
  2. Eric的答案中的Add方法不存在(带有该签名)。
  3. 由于MemoryCache只是抽象类ObjectCache的一个实现,并且它不使用任何MemoryCache特定函数,我基于ObjectCache

    AddOrGetExisting上完整实施ObjectCache方法的通用版本:

        public static T AddOrGetExisting<T>(ObjectCache cache, string key, Func<(T item, CacheItemPolicy policy)> addFunc)
        {
            object cachedItem = cache.Get(key);
            if (cachedItem is T t)
                return t;
            (T item, CacheItemPolicy policy) = addFunc();
            cache.Add(key, item, policy);
            return item;
        }
    

    请注意,这使用了所提到的C#7增强功能以​​及System.ValueTuple,如果使用net461或更高版本或内置于netstandard2.0,则可以从NuGet获取

    我的GitHub存储库CZEMacLeod/ObjectCacheExtensions

    中提供了完整的扩展类,以及Get和TryGetValue的通用版本,以及AddOrGetExisting的许多其他重载。