MemoryCache.Set return removed cache item

感情迁移 提交于 2020-01-24 10:49:45

问题


I am using the .NET 4.0 MemoryCache class, and I want to add or replace an existing item in the cache in a thread-safe manner, but I also want to know whether I have replaced an existing item or added a new one.

From what I can tell, the Set method is intended for the purpose of atomically replacing an item in the cache if it exists, whereas the AddOrGetExisting method will atomically get me the existing item without replacing it.

However, the Set method doesn't return the item that was replaced, it just replaces it. It is possible to hook up a removed event to the CacheItemPolicy for items, but hard to match that up with the new item that replaced it.

I can approximate it with the following method, but it seems a bit heavy (because of asking the cache to essentially add an item twice) and I wanted to ask if someone knows an easier way to do it.

public object SetAndGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
{
    lock (_cacheLock)
    {
        var existing = _cache.AddOrGetExisting(key, value, policy, regionName);

        if (existing != null)
        {
            _cache.Set(key, value, policy, regionName);
            return existing;
        }

        return null;
    }
}

回答1:


After thinking about it, in your example, you are updating it regardless, so AddOrGetExisting isn't the best, as you mentioned, you are setting it later anyway. Below it a simple implementation that I think fits what you are asking for. If I am wrong, please let me know!

public class MemoryCacheWithEvents
{
    private static MemoryCache _cache = new MemoryCache("myCache");
    private static object _syncLock = new object();

    public EventHandler<CacheChangeEventArgs> AddingCacheItem;
    public EventHandler<CacheChangeEventArgs> UpdatingCacheItem;


    public object GetAndSetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
    {
        lock (_syncLock)
        {
            var cacheItem = new CacheItem(key, value, regionName);

            var existing = _cache.GetCacheItem(key, null);

            if (existing == null)
            {
                OnAddingCacheItem(new CacheChangeEventArgs(null, cacheItem));
            }
            else
            {
                OnUpdatingCacheItem(new CacheChangeEventArgs(existing, cacheItem));   
            }

            _cache.Set(cacheItem, policy);

            return existing;
        }
    }

    public virtual void OnAddingCacheItem(CacheChangeEventArgs eventArgs){
        var handler = AddingCacheItem;

        if (handler != null)
        {
            handler(this, eventArgs);
        }
    }

    public virtual void OnUpdatingCacheItem(CacheChangeEventArgs eventArgs){
        var handler = UpdatingCacheItem;

        if (handler != null)
        {
            handler(this, eventArgs);
        }
    }
}

public class CacheChangeEventArgs : EventArgs
{
    public object OldCacheItem { get; set; }
    public object NewCacheItem { get; set; }

    public CacheChangeEventArgs(object oldCacheItem, object newCacheItem)
    {
        this.OldCacheItem = oldCacheItem;
        this.NewCacheItem = newCacheItem;
    }
}


来源:https://stackoverflow.com/questions/16018009/memorycache-set-return-removed-cache-item

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!