是否有用于缓存数据的通用c#源代码?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否有用于缓存数据的通用c#源代码?相关的知识,希望对你有一定的参考价值。
[每次使用数据缓存时,我都必须“发明”几乎相同的样板代码,包括缓存密钥生成,获取(设置)缓存值以及清除缓存。
这通常是这样的:
...
var cache = new Dictionary<string, string>();
var cacheKey = "some_kind_of_cache_key";
if (cache.ContainsKey(cacheKey))
{
return cache[cacheKey];
}
string newCacheValue = MakeSomethingComplicated();
return cache[cacheKey] = newCacheValue;
我想看看是否有某种可重用的c#源代码用于缓存?
答案
这是我使用的:
public static class MemoryCacheExtensions
{
public static T GetOrSet<T>(this MemoryCache cache, string cacheKey, Func<T> callbackForSet,
out bool foundInCache, DateTimeOffset? absoluteExpiration = null)
{
foundInCache = true;
var cacheItem = cache[cacheKey];
if (cacheItem == null)
{
foundInCache = false;
cacheItem = callbackForSet();
var absolExpir = absoluteExpiration ?? DateTimeOffset.UtcNow.AddMinutes(5);
cache.Set(cacheKey, cacheItem, absolExpir); // update or insert
}
return (T)cacheItem; // if you're scared of nulls then use: as T
}
}
您可以这样称呼它:
public static void Test()
{
var memCache = new MemoryCache("MyMemCache");
var cacheKey = "myCacheKey";
// the first time you call GetOrSet, it will set and return the value
var cachedValue = memCache.GetOrSet(cacheKey, () =>
{
return DateTime.Now;
}, out bool foundInCache);
Thread.Sleep(1000);
// the second time you call GetOrSet, it will return the cached value
var cachedValue2 = memCache.GetOrSet(cacheKey, () =>
{
// this will only be called if the cacheKey was not found
return DateTime.Now;
}, out foundInCache);
}
我的默认缓存持续时间是5分钟。您可以通过将第四个参数传递给GetOrSet来更改缓存持续时间
DateTimeOffset.UtcNow.AddMinutes(1); // for caching for 1 min
另一答案
是的,您可以如下创建基类:
public class BaseCache<TValue>
{
private readonly IDictionary<string, TValue> hash = new Dictionary<string, TValue>();
/// <summary>
/// gets the cache key parts as inputs: f.e. "keyPart1", "keyPart2", "keyPart3"
/// and turns them into the cache key in the form of "keyPart1_keyPart2_keyPart3"
/// </summary>
/// <param name="keyParts"></param>
/// <returns></returns>
private string CacheKey(IEnumerable<string> keyParts)
{
var keyPartsEnumerated = keyParts as string[] ?? keyParts.ToArray();
if (!keyPartsEnumerated.Any())
{
return String.Empty;
}
string retVal = keyPartsEnumerated.Aggregate(string.Empty, (acc, key) => string.IsNullOrEmpty(acc) ? $"{key}" : $"{acc}_{key}");
return retVal;
}
public void SetCacheValue(IEnumerable<string> keyParts, TValue value)
{
hash[CacheKey(keyParts)] = value;
}
public void SetCacheValue(string key, TValue value)
{
SetCacheValue(new[] { key }, value);
}
public bool TryGetCacheValue(IEnumerable<string> keyParts, out TValue value)
{
var cacheKey = CacheKey(keyParts);
return hash.TryGetValue(cacheKey, out value);
}
public bool TryGetCacheValue(string key, out TValue value)
{
return TryGetCacheValue(new[] { key }, out value);
}
private string[] GetCacheKeys_WhichStartWith(string startWith)
{
return hash.Where(p => p.Key.ToLower().StartsWith(startWith.ToLower())).Select(p => p.Key).ToArray();
}
public void ClearCache(string keyStartsWith)
{
if (string.IsNullOrEmpty(keyStartsWith))
{
return;
}
switch (keyStartsWith.ToLower())
{
case "all":
hash.Clear();
return;
default:
var envKeys = GetCacheKeys_WhichStartWith(keyStartsWith);
foreach (var envKey in envKeys) hash.Remove(envKey);
break;
}
}
}
,并将您的专用缓存导出为单例:
public sealed class ExampleCache : BaseCache<bool?>
{
private static readonly Lazy<ExampleCache> instance = new Lazy<ExampleCache>(() => new ExampleCache());
public static ExampleCache Instance => instance.Value;
private ExampleCache() { }
}
请参考到https://github.com/yugklim/CacheAsSingletonDemo.git
以上是关于是否有用于缓存数据的通用c#源代码?的主要内容,如果未能解决你的问题,请参考以下文章
Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题