您是否考虑过使用System.Web.Caching 而不必自己动手?
http://www.hanselman.com/blog/UsingTheASPNETCacheOutsideOfASPNET.aspx
编辑
上面不应该给系统增加太多的开销,但是看看这个。
以下代码中的一些健康警告。
- 不完整...见底部的
throw new NotImplementedException()s。我会尝试过一段时间再回来,因为这是一个有趣的谜题。
- 您可能希望改变到期的方式并覆盖添加方法以向构造值提供不同的值
- 我只在控制台应用程序中对其进行了最低限度的测试。查看测试代码
- 它还需要围绕 TKey 和 TValue 集合进行一些工作,因为它们会盲目地返回整个内部字典的集合,而无需任何过期检查……如果您不需要特别精细的过期。您可以将 system.timer 添加到定期遍历整个集合并删除过期条目的类中。
- 如果您查看 BCL 字典的定义,您会发现它实现了许多其他接口,因此根据您的要求,您可能也希望实现这些接口。
IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable, ISerializable, IDeserializationCallback
测试代码
TimeSpan t = new TimeSpan(0,0,5); //5 Second Expiry
ExpiringDictionary<int, string> dictionary
= new ExpiringDictionary<int,string>(t);
dictionary.Add(1, "Alice");
dictionary.Add(2, "Bob");
dictionary.Add(3, "Charlie");
//dictionary.Add(1, "Alice"); //<<this will throw a exception as normal...
System.Threading.Thread.Sleep(6000);
dictionary.Add(1, "Alice"); //<< this however should work fine as 6 seconds have passed
实施
public class ExpiringDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private class ExpiringValueHolder<T> {
public T Value { get; set; }
public DateTime Expiry { get; private set; }
public ExpiringValueHolder(T value, TimeSpan expiresAfter)
{
Value = value;
Expiry = DateTime.Now.Add(expiresAfter);
}
public override string ToString() { return Value.ToString(); }
public override int GetHashCode() { return Value.GetHashCode(); }
};
private Dictionary<TKey, ExpiringValueHolder<TValue>> innerDictionary;
private TimeSpan expiryTimeSpan;
private void DestoryExpiredItems(TKey key)
{
if (innerDictionary.ContainsKey(key))
{
var value = innerDictionary[key];
if (value.Expiry < System.DateTime.Now)
{
//Expired, nuke it in the background and continue
innerDictionary.Remove(key);
}
}
}
public ExpiringDictionary(TimeSpan expiresAfter)
{
expiryTimeSpan = expiresAfter;
innerDictionary = new Dictionary<TKey, ExpiringValueHolder<TValue>>();
}
public void Add(TKey key, TValue value)
{
DestoryExpiredItems(key);
innerDictionary.Add(key, new ExpiringValueHolder<TValue>(value, expiryTimeSpan));
}
public bool ContainsKey(TKey key)
{
DestoryExpiredItems(key);
return innerDictionary.ContainsKey(key);
}
public bool Remove(TKey key)
{
DestoryExpiredItems(key);
return innerDictionary.Remove(key);
}
public ICollection<TKey> Keys
{
get { return innerDictionary.Keys; }
}
public bool TryGetValue(TKey key, out TValue value)
{
bool returnval = false;
DestoryExpiredItems(key);
if (innerDictionary.ContainsKey(key))
{
value = innerDictionary[key].Value;
returnval = true;
} else { value = default(TValue);}
return returnval;
}
public ICollection<TValue> Values
{
get { return innerDictionary.Values.Select(vals => vals.Value).ToList(); }
}
public TValue this[TKey key]
{
get
{
DestoryExpiredItems(key);
return innerDictionary[key].Value;
}
set
{
DestoryExpiredItems(key);
innerDictionary[key] = new ExpiringValueHolder<TValue>(value, expiryTimeSpan);
}
}
public void Add(KeyValuePair<TKey, TValue> item)
{
DestoryExpiredItems(item.Key);
innerDictionary.Add(item.Key, new ExpiringValueHolder<TValue>(item.Value, expiryTimeSpan));
}
public void Clear()
{
innerDictionary.Clear();
}
public int Count
{
get { return innerDictionary.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
}