live-forum/server/webapi/LiveForum/LiveForum.Code/SystemCache/SystemCacheServiceBase.cs
2026-03-24 11:27:37 +08:00

129 lines
3.8 KiB
C#

using LiveForum.Code.Redis.Contract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace LiveForum.Code.SystemCache
{
/// <summary>
/// 系统缓存服务基类(用于底层支持需要的系统级缓存)
/// </summary>
/// <typeparam name="TValue">缓存值类型</typeparam>
/// <typeparam name="TKey">键类型(用于从缓存值中提取键)</typeparam>
public abstract class SystemCacheServiceBase<TValue, TKey> : ISystemCacheService<TValue>
where TKey : notnull
{
protected readonly IRedisService _redisService;
protected abstract string CacheKey { get; }
protected abstract TimeSpan CacheExpiration { get; }
protected SystemCacheServiceBase(IRedisService redisService)
{
_redisService = redisService;
}
/// <summary>
/// 从缓存值中提取键(子类需要实现)
/// </summary>
/// <param name="value">缓存值</param>
/// <returns>键</returns>
protected abstract TKey GetKeyFromValue(TValue value);
/// <summary>
/// 从数据库加载所有数据(子类需要实现)
/// </summary>
/// <returns>数据列表</returns>
protected abstract Task<List<TValue>> LoadFromDatabaseAsync();
/// <summary>
/// 获取所有缓存数据(从缓存或数据库加载)
/// </summary>
public virtual async Task<List<TValue>> GetAllAsync()
{
try
{
// 先从缓存获取
var cachedData = await _redisService.GetAsync<List<TValue>>(CacheKey);
if (cachedData != null && cachedData.Any())
{
return cachedData;
}
// 缓存未命中,从数据库加载
var data = await LoadFromDatabaseAsync();
if (data != null && data.Any())
{
// 写入缓存
await _redisService.SetAsync(CacheKey, data, CacheExpiration);
}
return data ?? new List<TValue>();
}
catch (Exception ex)
{
// 记录错误但不抛出异常,尝试从数据库加载
// 可以在这里添加日志记录
return await LoadFromDatabaseAsync() ?? new List<TValue>();
}
}
/// <summary>
/// 根据键获取缓存数据
/// </summary>
public virtual async Task<TValue> GetByKeyAsync(object key)
{
if (key == null)
{
return default(TValue);
}
var allData = await GetAllAsync();
TKey keyValue;
if (key is TKey directKey)
{
keyValue = directKey;
}
else
{
try
{
keyValue = (TKey)Convert.ChangeType(key, typeof(TKey));
}
catch
{
return default(TValue);
}
}
return allData.FirstOrDefault(x => GetKeyFromValue(x).Equals(keyValue));
}
/// <summary>
/// 清除缓存
/// </summary>
public virtual async Task ClearCacheAsync()
{
try
{
await _redisService.RemoveAsync(CacheKey);
}
catch
{
// 忽略缓存清除错误
}
}
/// <summary>
/// 刷新缓存(清除并重新加载)
/// </summary>
public virtual async Task RefreshCacheAsync()
{
await ClearCacheAsync();
await GetAllAsync();
}
}
}