using Microsoft.Extensions.Caching.Distributed;
|
using Microsoft.Extensions.Caching.Memory;
|
using Newtonsoft.Json;
|
using SqlSugar;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using WIDESEAWCS_Core.Helper;
|
|
namespace WIDESEAWCS_Core.Caches
|
{
|
public class MemoryCacheService : ICacheService
|
{
|
protected IMemoryCache _cache;
|
public MemoryCacheService(IMemoryCache cache)
|
{
|
_cache = cache;
|
|
}
|
|
public bool Add(string key, string value, int expireSeconds = -1, bool isSliding = false)
|
{
|
return AddObject(key, value, expireSeconds, isSliding);
|
}
|
|
public bool AddObject(string key, object value, int expireSeconds = -1, bool isSliding = false)
|
{
|
if (expireSeconds > 0)
|
{
|
_cache.Set(key,
|
value,
|
new MemoryCacheEntryOptions()
|
.SetSlidingExpiration(new TimeSpan(0, 0, expireSeconds))
|
);
|
}
|
else
|
{
|
_cache.Set(key, value);
|
}
|
|
return true;
|
}
|
|
public void AddOrUpdate(string key, string value, int expireSeconds = -1, bool isSliding = false)
|
{
|
if (!string.IsNullOrEmpty(Get(key)))
|
{
|
Remove(key);
|
Add(key, value, expireSeconds, isSliding);
|
}
|
else
|
{
|
Add(key, value, expireSeconds, isSliding);
|
}
|
}
|
|
public void AddOrUpdate(string key, object value, int expireSeconds = -1, bool isSliding = false)
|
{
|
if (!string.IsNullOrEmpty(Get(key)))
|
{
|
Remove(key);
|
Add(key, value.Serialize(), expireSeconds, isSliding);
|
}
|
else
|
{
|
Add(key, value.Serialize(), expireSeconds, isSliding);
|
}
|
}
|
|
public void Dispose()
|
{
|
if (_cache != null)
|
_cache.Dispose();
|
GC.SuppressFinalize(this);
|
}
|
|
public bool Exists(string key)
|
{
|
if (key == null)
|
{
|
throw new ArgumentNullException(nameof(key));
|
}
|
return _cache.Get(key) != null;
|
}
|
|
public T? Get<T>(string key) where T : class
|
{
|
if (key == null)
|
{
|
throw new ArgumentNullException(nameof(key));
|
}
|
object? value = _cache.Get(key);
|
if (value == null)
|
{
|
throw new ArgumentNullException(nameof(key));
|
}
|
return value as T;
|
}
|
|
public string? Get(string key)
|
{
|
try
|
{
|
return _cache.Get(key)?.ToString();
|
}
|
catch
|
{
|
return string.Empty;
|
}
|
}
|
|
public object? Get(Type type, string key)
|
{
|
try
|
{
|
object res = _cache.Get(key);
|
return res == null ? default : JsonConvert.DeserializeObject(res?.ToString() ?? "{}", type);
|
}
|
catch
|
{
|
return string.Empty;
|
}
|
}
|
|
public bool Remove(string key)
|
{
|
if (key == null)
|
{
|
throw new ArgumentNullException(nameof(key));
|
}
|
_cache.Remove(key);
|
|
return !Exists(key);
|
}
|
|
public void Remove(IEnumerable<string> keys)
|
{
|
if (keys == null)
|
{
|
throw new ArgumentNullException(nameof(keys));
|
}
|
|
keys.ToList().ForEach(item => _cache.Remove(item));
|
}
|
|
#region 删除扩展方法
|
|
public string? RemoveAndGet(string key)
|
{
|
var value = Get(key);
|
if (value != null) _cache.Remove(key);
|
return value;
|
}
|
|
public T? RemoveAndGet<T>(string key) where T : class
|
{
|
var value = Get<T>(key);
|
if (value != null) _cache.Remove(key);
|
return value;
|
}
|
|
public int RemoveByPrefix(string prefix)
|
{
|
if (string.IsNullOrEmpty(prefix)) return 0;
|
// MemoryCache不支持枚举,返回0
|
return 0;
|
}
|
|
public int RemoveByPattern(string pattern)
|
{
|
// MemoryCache不支持模式匹配
|
return 0;
|
}
|
|
public int RemoveAll(IEnumerable<string> keys)
|
{
|
if (keys == null) return 0;
|
int count = 0;
|
foreach (var key in keys)
|
{
|
if (Remove(key)) count++;
|
}
|
return count;
|
}
|
|
public int RemoveWhere(Func<string, bool> predicate)
|
{
|
// MemoryCache不支持枚举所有Key
|
return 0;
|
}
|
|
#endregion
|
|
#region 添加和修改扩展方法
|
|
public void AddAll(IDictionary<string, string> items, int expireSeconds = -1)
|
{
|
if (items == null) return;
|
foreach (var item in items)
|
{
|
Add(item.Key, item.Value, expireSeconds);
|
}
|
}
|
|
public void AddAllObjects(IDictionary<string, object> items, int expireSeconds = -1)
|
{
|
if (items == null) return;
|
foreach (var item in items)
|
{
|
AddObject(item.Key, item.Value, expireSeconds);
|
}
|
}
|
|
public bool Replace(string key, string newValue, int expireSeconds = -1)
|
{
|
return TryUpdate(key, newValue, expireSeconds);
|
}
|
|
public bool Replace<T>(string key, T newValue, int expireSeconds = -1) where T : class
|
{
|
if (!Exists(key)) return false;
|
AddObject(key, newValue, expireSeconds);
|
return true;
|
}
|
|
public string? GetAndRefresh(string key, int expireSeconds)
|
{
|
var value = Get(key);
|
if (value != null)
|
{
|
Add(key, value, expireSeconds);
|
return value;
|
}
|
return null;
|
}
|
|
public T? GetAndRefresh<T>(string key, int expireSeconds) where T : class
|
{
|
var value = Get<T>(key);
|
if (value != null)
|
{
|
AddObject(key, value, expireSeconds);
|
return value;
|
}
|
return default;
|
}
|
|
public bool RefreshExpire(string key, int expireSeconds)
|
{
|
var value = Get(key);
|
if (value != null)
|
{
|
Add(key, value, expireSeconds);
|
return true;
|
}
|
return false;
|
}
|
|
public bool ExpireIn(string key, int seconds)
|
{
|
return RefreshExpire(key, seconds);
|
}
|
|
public bool ExpireAt(string key, DateTime expireTime)
|
{
|
var seconds = (int)(expireTime - DateTime.Now).TotalSeconds;
|
if (seconds <= 0) return Remove(key);
|
return RefreshExpire(key, seconds);
|
}
|
|
public long? GetExpire(string key)
|
{
|
return null; // MemoryCache不支持TTL查询
|
}
|
|
public bool AddIfNotExists(string key, string value, int expireSeconds = -1)
|
{
|
return TryAdd(key, value, expireSeconds);
|
}
|
|
public bool AddIfNotExists<T>(string key, T value, int expireSeconds = -1) where T : class
|
{
|
return TryAdd(key, value, expireSeconds);
|
}
|
|
public string? GetAndSet(string key, string newValue, int expireSeconds = -1)
|
{
|
var oldValue = Get(key);
|
Add(key, newValue, expireSeconds);
|
return oldValue;
|
}
|
|
public T? GetAndSet<T>(string key, T newValue, int expireSeconds = -1) where T : class
|
{
|
var oldValue = Get<T>(key);
|
AddObject(key, newValue, expireSeconds);
|
return oldValue;
|
}
|
|
public long Increment(string key, long value = 1)
|
{
|
var current = long.TryParse(Get(key), out var v) ? v : 0;
|
var newValue = current + value;
|
Add(key, newValue.ToString());
|
return newValue;
|
}
|
|
public long Decrement(string key, long value = 1)
|
{
|
return Increment(key, -value);
|
}
|
|
public long Append(string key, string value)
|
{
|
var current = Get(key) ?? "";
|
var newValue = current + value;
|
Add(key, newValue);
|
return newValue.Length;
|
}
|
|
#endregion
|
|
public bool TryAdd(string key, string value, int expireSeconds = -1)
|
{
|
if (Exists(key)) return false;
|
return Add(key, value, expireSeconds);
|
}
|
|
public bool TryAdd<T>(string key, T value, int expireSeconds = -1) where T : class
|
{
|
if (Exists(key)) return false;
|
return AddObject(key, value, expireSeconds);
|
}
|
|
public bool TryGetValue(string key, out string? value)
|
{
|
value = _cache.Get(key)?.ToString();
|
return value != null;
|
}
|
|
public bool TryGetValue<T>(string key, out T? value) where T : class
|
{
|
if (_cache.TryGetValue(key, out object? obj) && obj != null)
|
{
|
value = obj as T ?? JsonConvert.DeserializeObject<T>(obj.ToString() ?? "");
|
return value != null;
|
}
|
value = default;
|
return false;
|
}
|
|
public bool TryRemove(string key, out string? value)
|
{
|
value = _cache.Get(key)?.ToString();
|
if (value == null) return false;
|
_cache.Remove(key);
|
return true;
|
}
|
|
public bool TryUpdate(string key, string newValue, int expireSeconds = -1)
|
{
|
if (!Exists(key)) return false;
|
Remove(key);
|
Add(key, newValue, expireSeconds);
|
return true;
|
}
|
|
public bool TryUpdateIfChanged(string key, string newValue, int expireSeconds = -1)
|
{
|
var existing = Get(key);
|
if (existing == null) return false;
|
if (existing == newValue) return false; // 值相同,不更新
|
Remove(key);
|
Add(key, newValue, expireSeconds);
|
return true;
|
}
|
|
public bool TryUpdateIfChanged<T>(string key, T newValue, int expireSeconds = -1) where T : class
|
{
|
var existing = Get<T>(key);
|
if (existing == null) return false;
|
|
// 使用JSON序列化比较内容,而不是引用比较
|
var existingJson = JsonConvert.SerializeObject(existing);
|
var newJson = JsonConvert.SerializeObject(newValue);
|
if (existingJson == newJson) return false; // JSON字符串相同,不更新
|
|
Remove(key);
|
AddObject(key, newValue, expireSeconds);
|
return true;
|
}
|
|
public string GetOrAdd(string key, string value, int expireSeconds = -1)
|
{
|
var existing = _cache.Get(key)?.ToString();
|
if (existing != null) return existing;
|
Add(key, value, expireSeconds);
|
return value;
|
}
|
|
public string GetOrAdd(string key, Func<string, string> valueFactory, int expireSeconds = -1)
|
{
|
var existing = _cache.Get(key)?.ToString();
|
if (existing != null) return existing;
|
var value = valueFactory(key);
|
Add(key, value, expireSeconds);
|
return value;
|
}
|
|
public T GetOrAdd<T>(string key, Func<string, T> valueFactory, int expireSeconds = -1) where T : class
|
{
|
if (_cache.TryGetValue(key, out object? obj) && obj != null)
|
{
|
if (obj is T t) return t;
|
var deserialized = JsonConvert.DeserializeObject<T>(obj.ToString() ?? "");
|
if (deserialized != null) return deserialized;
|
}
|
var value = valueFactory(key);
|
AddObject(key, value, expireSeconds);
|
return value;
|
}
|
}
|
}
|