我想创建一个类来返回一个值。此值将缓存在字典对象中2分钟。在这2分钟内,我需要返回缓存的值,在那几分钟之后,字典缓存对象应该再次读取该值。我需要使用Dictionary对象而不是memorychache或者其他东西我应该在Test方法类中执行代码而不是windows窗体或wpf。
我不知道如何在测试方法中使字典对象在2分钟后过期。
public class CacheClass
{
public string GetValue()
{
Dictionary<int, string> Cache = new Dictionary<int, string>();
string value1 = "Lina";
string value2 = "Jack";
return "cached value";
}
}
public class Cache<TKey, TValue>
{
private readonly Dictionary<TKey, CacheItem<TValue>> _cache = new Dictionary<TKey, CacheItem<TValue>>();
public void Store(TKey key, TValue value, TimeSpan expiresAfter)
{
_cache[key] = new CacheItem<TValue>(value, expiresAfter);
}
public TValue Get(TKey key)
{
if (!_cache.ContainsKey(key)) return default(TValue);
var cached = _cache[key];
if (DateTimeOffset.Now - cached.Created >= cached.ExpiresAfter)
{
_cache.Remove(key);
return default(TValue);
}
return cached.Value;
}
}
public class CacheItem<T>
{
public CacheItem(T value, TimeSpan expiresAfter)
{
Value = value;
ExpiresAfter = expiresAfter;
}
public T Value { get; }
internal DateTimeOffset Created { get; } = DateTimeOffset.Now;
internal TimeSpan ExpiresAfter { get; }
}
var cache = new Cache<int, string>();
cache.Store(1, "SomeString", TimeSpan.FromMinutes(2));
我将创建一个新的缓存项类型,跟踪值以及项添加到缓存的时间:
class CacheItem<T>
{
public T Value { get; }
public DateTime TimeAdded { get; }
public bool IsValid => (DateTime.UtcNow - TimeAdded) < _timeToLive;
private readonly TimeSpam _timeToLive = TimeSpan.FromMinutes(2);
public CacheItem(T value)
{
Value = value;
TimeAdded = DateTime.UtcNow;
}
}
然后将缓存集合更改为Dictionary<int, CacheItem<string>>
public string GetValue(int key)
{
CacheItem<string> item;
if (_cache.TryGetValue(key, out item) && item.IsValid)
return item.Value;
return null; // Signifies no entry in cache or entry has expired.
}
您需要将日期时间存储在缓存中。这样,您可以测试项目是否已过期。如果物品未找到或过期?为它调用resolvefunction。
这是一个缓存的例子,可以通过调用回调函数来填充它:
public class MyCache<TKey, TValue>
{
// type to store datetime and a value
private struct CacheItem
{
public DateTime RetreivedTime;
public TValue Value;
}
// the dictionary
private Dictionary<TKey, CacheItem> _cache = new Dictionary<TKey, CacheItem>();
private TimeSpan _timeout;
private Func<TKey, TValue> _resolveFunc;
public MyCache(TimeSpan timeout, Func<TKey, TValue> resolveFunc)
{
// store to fields
_timeout = timeout;
_resolveFunc = resolveFunc;
}
public TValue this[TKey key]
{
get
{
CacheItem valueWithDateTime;
// if nothing is found, you should resolve it by default
var getNewValue = true;
// lookup the key
if (_cache.TryGetValue(key, out valueWithDateTime))
// test if the value RetreivedTime was expired?
getNewValue = valueWithDateTime.RetreivedTime.Add(_timeout) > DateTime.UtcNow;
// was it found? or expired?
if (getNewValue)
{
valueWithDateTime = new CacheItem { RetreivedTime = DateTime.UtcNow, Value = _resolveFunc(key) };
_cache[key] = valueWithDateTime;
}
// return the value
return valueWithDateTime.Value;
}
}
// the cleanup method, you should call it sometimes...
public void Cleanup()
{
var currentDateTime = DateTime.UtcNow;
// ToArray prevents modifying an iterated collection.
foreach (var keyValue in _cache.ToArray())
if (keyValue.Value.RetreivedTime.Add(_timeout) < currentDateTime)
_cache.Remove(keyValue.Key);
}
}
缓存文本文件的示例:
class Program
{
static string RetreiveFileContent(string filename)
{
if(!File.Exists(filename))
return default(string);
return File.ReadAllText(filename);
}
static void Main(string[] args)
{
var textFileCache = new MyCache<string, string>(TimeSpan.FromMinutes(2), RetreiveFileContent);
var content = textFileCache["helloworld.txt"];
// sometimes you need to cleanup old data.
textFileCache.Cleanup();
}
}
你需要创建一些事件的异常处理....
我想你想要更简单的事情。根据你的解释,我无法弄清楚为什么你需要一个字典或集合?因为,你的CacheClass
只有一个GetValue
方法,而且一个项目不是从外面添加的。
所以,试试这样的事情也许会给你一个起点;
public class CacheObject
{
public string Value { get; set; }
public DateTime CreationDate { get; set; }
public CacheObject()
{
CreationDate = DateTime.Now;
}
}
public static class CacheClass
{
private static Dictionary<int,CacheObject> _cache = new Dictionary<int, CacheObject>();
public static string GetValue()
{
if (_cache.Count == 0 || _cache[0].CreationDate.AddMinutes(2) < DateTime.Now)
{
var cache = new CacheObject
{
Value = GetValueFromSource()
};
_cache[0] = cache;
}
return _cache[0].Value;
}
public static string GetValueFromSource()
{
return "Jack";
}
}
用法;
var str = CacheClass.GetValue();