在这种情况下,您的缓存不应缓存实际对象,而是缓存对象的包装器,该包装器还包含有关缓存中对象状态的信息。
例如,您可以有一个像这样的简单类,表示缓存中的项目:
public class CacheItem<T>
{
// Since the cache is the only thing
// that should be making CacheItems,
// make this internal to the assembly
// that the cache is implemented in.
// This constructor is called before
// an add.
internal CacheItem(T item)
{
// Set the property values.
Item = item;
}
// Poor-man's immutability.
public T Item { get; private set; }
// The backing field for IsCached, it
// is volatile so that it can serialize
// access for single reads/writes, which is
// what the property does.
// Assume it is being added when constructed.
private volatile bool _isCached = true;
// Only able to be set by the cache.
// The setter is set to false when the item
// is stale (not in the cache any longer).
public bool IsCached
{
get { return _isCached; }
set { _isCached = value; }
}
}
这里的想法很简单:
当你的缓存即将向缓存中输入一个项目的新实例时,它会调用构造函数(构造函数应该只对缓存可用,如果需要,你可以CacheItem
使用私有构造函数而不是内部构造嵌套类)它将IsCached
属性值设置为 true。然后将该项目放置在缓存中。
当项目从缓存中过期时,缓存将该IsCached
属性设置为 false(同样,该属性应该只能由缓存访问)。
责任转移到客户端来检查CacheItem<T>
它是否过时。
请注意,这是一个拉操作。如果需要,您可以通过添加事件来添加推送CacheItem<T>
操作支持,如下所示:
public class CacheItem<T>
{
// Since the cache is the only thing
// that should be making CacheItems,
// make this internal to the assembly
// that the cache is implemented in.
// This constructor is called before
// an add.
internal CacheItem(T item)
{
// Set the property values.
Item = item;
}
// Poor-man's immutability.
public T Item { get; private set; }
// The lock for the event registrations.
// Since everything else is immutable, this needs
// to be as well.
private readonly object _eventLock = new object();
// The backing field for the Expired
// event. Since everything else is immutable
// this needs to be as well.
private readonly EventHandler _expiredHandlers;
// The expires event.
public event EventHandler Expired
{
add { lock (_eventLock) _expiredHandlers += value; }
remove { lock (_eventLock) _expiredHandlers -= value; }
}
// The backing field for IsCached, it
// is volatile so that it can serialize
// access for single reads/writes, which is
// what the property does.
// Assume it is being added when constructed.
private volatile bool _isCached = true;
// The setter is set to false by the
// Expire method (called by the cached)
// when the item is stale
// (not in the cache any longer).
public bool IsCached { get { return _isCached; } }
// Called internally by the cache.
internal void Expire()
{
// Set _isCached to false.
_isCached = false;
// Get the event handlers and fire
// the event. Getting the handlers
// needs to be synchronized.
EventHandler handlers;
// Synchronize.
lock (_eventLock) handlers = _expiredHandlers;
// Fire if there are handlers.
if (handlers != null) handlers(this, EventArgs.Empty);
}
}
现在,您可以让您的客户端订阅该Expired
事件,这将在缓存项无效时向客户端指示。Expire
当它从缓存中删除时,缓存会通过调用该项目的内部事件来触发它(并且它也会将该IsCached
属性设置为 false)。