87 lines
2.4 KiB
C#
87 lines
2.4 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace LiveForum.Code.SystemCache
|
|
{
|
|
/// <summary>
|
|
/// 字段缓存服务基类(提供通用的字段缓存实现)
|
|
/// </summary>
|
|
/// <typeparam name="TValue">缓存值类型</typeparam>
|
|
public abstract class FieldCacheServiceBase<TValue> : IFieldCacheService<TValue>
|
|
{
|
|
private TValue _cachedValue;
|
|
private readonly object _cacheLock = new object();
|
|
|
|
/// <summary>
|
|
/// 加载数据的方法(子类需要实现)
|
|
/// </summary>
|
|
/// <returns>数据值</returns>
|
|
protected abstract Task<TValue> LoadDataAsync();
|
|
|
|
/// <summary>
|
|
/// 获取缓存值(如果缓存不存在,会调用加载方法)
|
|
/// </summary>
|
|
public virtual async Task<TValue> GetAsync()
|
|
{
|
|
// 如果缓存存在,直接返回(同一请求内共享)
|
|
if (_cachedValue != null && !IsNullValue(_cachedValue))
|
|
{
|
|
return _cachedValue;
|
|
}
|
|
|
|
// 首次调用,加载数据并缓存
|
|
// 注意:这里先加载数据,再锁定设置缓存,避免在 lock 内执行异步操作
|
|
var loadedValue = await LoadDataAsync();
|
|
|
|
lock (_cacheLock)
|
|
{
|
|
// 双重检查,避免并发加载
|
|
if (_cachedValue != null && !IsNullValue(_cachedValue))
|
|
{
|
|
return _cachedValue;
|
|
}
|
|
|
|
_cachedValue = loadedValue;
|
|
}
|
|
|
|
return _cachedValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清除实例字段缓存
|
|
/// </summary>
|
|
public virtual void ClearCache()
|
|
{
|
|
lock (_cacheLock)
|
|
{
|
|
_cachedValue = default(TValue);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 刷新缓存(清除并重新加载)
|
|
/// </summary>
|
|
public virtual async Task RefreshCacheAsync()
|
|
{
|
|
ClearCache();
|
|
await GetAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 判断值是否为空(处理值类型和引用类型)
|
|
/// </summary>
|
|
private bool IsNullValue(TValue value)
|
|
{
|
|
if (value == null)
|
|
return true;
|
|
|
|
// 对于字符串,检查是否为空
|
|
if (value is string str)
|
|
return string.IsNullOrWhiteSpace(str);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|