123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- using System.Collections;
- using EasyCaching.Core;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Options;
- using XF.Domain.Cache;
- namespace Hotline.EasyCaching
- {
- public class DefaultTypedCache<TValue> : ITypedCache<TValue>
- {
- private readonly IServiceScopeFactory _serviceScopeFactory;
- private readonly IHybridCachingProvider _hybridCaching;
- private readonly IRedisCachingProvider _redisCaching;
- private readonly IEasyCachingProvider _caching;
- private readonly TimeSpan _expirationDefault = TimeSpan.FromDays(1);
- public DefaultTypedCache(
- IServiceScopeFactory serviceScopeFactory,
- IHybridCachingProvider hybridCaching,
- IRedisCachingProvider redisCaching,
- IEasyCachingProvider caching
- )
- {
- _serviceScopeFactory = serviceScopeFactory;
- _hybridCaching = hybridCaching;
- _redisCaching = redisCaching;
- _caching = caching;
- }
- public void Set(string key, TValue value, TimeSpan? expiration = null) =>
- _hybridCaching.Set(CombinePrefix(key), value, expiration.GetValueOrDefault(_expirationDefault));
- public async Task SetAsync(string key, TValue value, TimeSpan? expiration = null, CancellationToken cancellationToken = default) =>
- await _hybridCaching.SetAsync(CombinePrefix(key), value, expiration.GetValueOrDefault(_expirationDefault), cancellationToken);
- public TValue? Get(string key) => _hybridCaching.Get<TValue>(CombinePrefix(key)).Value;
- public async Task<TValue> GetAsync(string key, CancellationToken cancellationToken) =>
- (await _hybridCaching.GetAsync<TValue>(CombinePrefix(key), cancellationToken)).Value;
- public void Remove(string key) => _hybridCaching.Remove(CombinePrefix(key));
- public async Task RemoveAsync(string key, CancellationToken cancellationToken) =>
- await _hybridCaching.RemoveAsync(CombinePrefix(key), cancellationToken);
- public bool Exists(string key) => _hybridCaching.Exists(CombinePrefix(key));
- public async Task<bool> ExistsAsync(string key, CancellationToken cancellationToken) =>
- await _hybridCaching.ExistsAsync(CombinePrefix(key), cancellationToken);
- public bool TrySet(string key, TValue value, TimeSpan? expiration = null) =>
- _hybridCaching.TrySet(CombinePrefix(key), value, expiration.GetValueOrDefault(_expirationDefault));
- public async Task<bool> TrySetAsync(string key, TValue value, TimeSpan? expiration = null, CancellationToken cancellationToken = default) =>
- await _hybridCaching.TrySetAsync(CombinePrefix(key), value, expiration.GetValueOrDefault(_expirationDefault), cancellationToken);
- public void SetAll(IDictionary<string, TValue> values, TimeSpan? expiration = null)
- {
- var newDic = new Dictionary<string, TValue>();
- foreach (var kvp in values)
- {
- newDic.Add(CombinePrefix(kvp.Key), kvp.Value);
- }
- _hybridCaching.SetAll(newDic, expiration.GetValueOrDefault(_expirationDefault));
- }
- public async Task SetAllAsync(IDictionary<string, TValue> values, TimeSpan? expiration = null, CancellationToken cancellationToken = default)
- {
- var newDic = new Dictionary<string, TValue>();
- foreach (var kvp in values)
- {
- newDic.Add(CombinePrefix(kvp.Key), kvp.Value);
- }
- await _hybridCaching.SetAllAsync(newDic, expiration.GetValueOrDefault(_expirationDefault), cancellationToken);
- }
- public IDictionary<string, TValue> GetByPrefix()
- {
- var cacheValueDic = _caching.GetByPrefix<TValue>(CreateRegion());
- if (cacheValueDic == null) return new Dictionary<string, TValue>();
- return cacheValueDic.ToDictionary(cacheValue => cacheValue.Key, cacheValue => cacheValue.Value.Value);
- }
- public async Task<IDictionary<string, TValue>> GetByPrefixAsync(CancellationToken cancellationToken)
- {
- var cacheValueDic = await _caching.GetByPrefixAsync<TValue>(CreateRegion(), cancellationToken);
- if (cacheValueDic == null) return new Dictionary<string, TValue>();
- return cacheValueDic.ToDictionary(cacheValue => cacheValue.Key, cacheValue => cacheValue.Value.Value);
- }
- public IReadOnlyList<TValue> GetListByPrefix()
- {
- var cacheValueDic = _caching.GetByPrefix<TValue>(CreateRegion());
- if (cacheValueDic == null) return new List<TValue>();
- return cacheValueDic.Values.Select(d => d.Value).ToList();
- }
- public async Task<IReadOnlyList<TValue>> GetListByPrefixAsync(CancellationToken cancellationToken)
- {
- var cacheValueDic = await _caching.GetByPrefixAsync<TValue>(CreateRegion(), cancellationToken);
- if (cacheValueDic == null) return new List<TValue>();
- return cacheValueDic.Values.Select(d => d.Value).ToList();
- }
- /// <summary>
- /// get the cache value, if cache not exists, set the value to cache then return
- /// </summary>
- public TValue GetOrSet(string key, TValue value, TimeSpan? expiration = null)
- {
- var cacheValue = Get(key);
- if (cacheValue != null) return cacheValue;
- Set(key, value, expiration);
- return value;
- }
- public TValue? GetOrSet(string key, Func<string, TValue> valueFactory, TimeSpan? expiration = null)
- {
- var cacheValue = Get(key);
- if (cacheValue != null) return cacheValue;
- var value = valueFactory.Invoke(key);
- if (value == null) return default;
- Set(key, value, expiration);
- return value;
- }
- public async Task<TValue> GetOrSetAsync(string key, TValue value, TimeSpan? expiration = null, CancellationToken cancellationToken = default)
- {
- var cacheValue = await GetAsync(key, cancellationToken);
- if (cacheValue != null) return cacheValue;
- await SetAsync(key, value, expiration, cancellationToken);
- return value;
- }
- public async Task<TValue?> GetOrSetAsync(string key, Func<string, TValue> valueFactory, TimeSpan? expiration = null, CancellationToken cancellationToken = default)
- {
- var cacheValue = await GetAsync(key, cancellationToken);
- if (cacheValue != null) return cacheValue;
- var value = valueFactory.Invoke(key);
- if (value == null) return default;
- await SetAsync(key, value, expiration, cancellationToken);
- return value;
- }
- public string CombinePrefix(string key) => CreateRegion() + key;
- private string CreateRegion()
- {
- var valueType = typeof(TValue);
- //if (valueType.IsGenericType)
- //{
- // throw new NotSupportedException("TCachedValue can not be a Generic Type");
- //}
- //if (valueType == typeof(string))
- //{
- // throw new NotSupportedException("TCachedValue can not be a string");
- //}
- if (string.IsNullOrWhiteSpace(valueType.FullName))
- {
- throw new NotSupportedException("FullName of type TCachedValue can not be null");
- }
- using var scope = _serviceScopeFactory.CreateScope();
- var options = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<CacheOptions>>();
- var prefix = options.Value.Prefix;
- //if (valueType.TryGetCustomAttribute<CacheAttribute>(false, out var attr))
- //{
- // if (!string.IsNullOrEmpty(attr.Region))
- // {
- // return attr.Region;
- // }
- //}
- string region;
- if (valueType.IsGenericType && valueType.GetInterfaces().Any(d => d == typeof(IEnumerable)))
- {
- region = "Collection";
- }
- else
- {
- region = valueType.FullName.Replace('.', ':');
- }
- if (!string.IsNullOrEmpty(prefix))
- {
- prefix += ':';
- if (!region.StartsWith(prefix))
- {
- region = prefix + region;
- }
- }
- return region;
- }
- }
- }
|