C# 设置返回已删除的缓存项

C# 设置返回已删除的缓存项,c#,.net,caching,C#,.net,Caching,我正在使用.NET 4.0类,我想以线程安全的方式在缓存中添加或替换现有项,但我也想知道我是否已替换现有项或添加新项 据我所知,该方法旨在以原子方式替换缓存中存在的项(如果存在),而该方法将以原子方式获取现有项而不替换它 但是,Set方法不会返回被替换的项,它只是替换它。可以将删除的事件连接到for项,但很难将其与替换它的新项匹配 我可以用下面的方法来近似它,但是它看起来有点重(因为要求缓存实质上添加一个项目两次),我想问一下是否有人知道一种更简单的方法来实现它 public object Se

我正在使用.NET 4.0类,我想以线程安全的方式在缓存中添加或替换现有项,但我也想知道我是否已替换现有项或添加新项

据我所知,该方法旨在以原子方式替换缓存中存在的项(如果存在),而该方法将以原子方式获取现有项而不替换它

但是,Set方法不会返回被替换的项,它只是替换它。可以将删除的事件连接到for项,但很难将其与替换它的新项匹配

我可以用下面的方法来近似它,但是它看起来有点重(因为要求缓存实质上添加一个项目两次),我想问一下是否有人知道一种更简单的方法来实现它

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;
    }
}

仔细考虑后,在您的示例中,您将对其进行更新,因此,
AddOrGetExisting
不是最好的,正如您所提到的,您将在稍后进行设置。下面是一个简单的实现,我认为它符合您的要求。如果我错了,请让我知道

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;
    }
}
公共类MemoryCacheWithEvents
{
私有静态MemoryCache_cache=新的MemoryCache(“myCache”);
私有静态对象_syncLock=新对象();
公共事件处理程序AddingCacheItem;
公共事件处理程序更新CacheItem;
公共对象GetAndSetExisting(字符串键、对象值、CacheItemPolicy策略、字符串regionName=null)
{
锁(同步锁)
{
var cacheItem=新的cacheItem(键、值、区域名称);
var existing=\u cache.GetCacheItem(key,null);
if(现有==null)
{
OnAddingCacheItem(新的CacheChangeEventArgs(null,cacheItem));
}
其他的
{
OnUpdatingCacheItem(新的CacheChangeEventArgs(现有的cacheItem));
}
_cache.Set(cacheItem,policy);
返回现有的;
}
}
添加CacheItem(CacheChangeEventArgs-eventArgs)上的公共虚拟无效{
var handler=AddingCacheItem;
if(处理程序!=null)
{
处理程序(此,eventArgs);
}
}
公共虚拟void OnUpdatingCacheItem(CacheChangeEventArgs-eventArgs){
var handler=updateingcacheitem;
if(处理程序!=null)
{
处理程序(此,eventArgs);
}
}
}
公共类CacheChangeEventArgs:EventArgs
{
公共对象OldCacheItem{get;set;}
公共对象NewCacheItem{get;set;}
public CacheChangeEventArgs(对象oldCacheItem、对象newCacheItem)
{
this.OldCacheItem=OldCacheItem;
this.NewCacheItem=NewCacheItem;
}
}

我不明白您为什么要调用set。如果为空,则表示它不存在并且已添加。您应该只返回AddOrGetExisting方法的结果。你想得太多了。因为如果有一个现有的项目,它不会添加我的新项目。AddOrGetExisting将仅在项目尚不存在时添加新项目。您是否尝试在这种情况下使用双重检查习惯用法?你可以阅读这篇维基百科文章的更多内容:你能提供一些关于你想要完成的事情的背景信息吗?设置一个新值似乎很有可能,即使在设置了新数据之后,您也会返回旧数据。对我来说,除非您出于某种原因将其记录下来,否则它的用处很小。我想不出在什么情况下,除了日志记录之外,知道该项目是否被添加或更新会很有用。似乎您有一个现有的类,所以您可以轻松地添加和事件并调用它:
public EventHandler AddedCacheItem;public EventHandler UpdatedCacheItem
并根据发生的情况调用它们。最简单的方法是使用AddOrGetExisting方法来确定执行了什么操作。是的,我自己也在考虑这个优化,非常感谢。我将把它标为答案。我正在使用Rx(反应式扩展)进行通知,但事件太老套了;-)虽然额外的锁定很遗憾,但我认为没有办法解决这个问题。