using System.Collections; using CacheManager.Core; using CacheManager.Core.Internal; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using XF.Domain.Cache; namespace CallCenter.CacheManager { public class DefaultTypedCache : ITypedCache where TValue : class { private readonly ICacheManager _cache; private readonly IServiceScopeFactory _serviceScopeFactory; private readonly string _region; public DefaultTypedCache(ICacheManager cache, IServiceScopeFactory serviceScopeFactory) { _cache = cache; _serviceScopeFactory = serviceScopeFactory; _region = CreateRegion(); } public bool Add(string key, TValue value, ExpireMode? expireMode = ExpireMode.None, TimeSpan? timeout = null) => _cache.Add(CreateCacheItem(key, value, expireMode, timeout)); public void Put(string key, TValue value, ExpireMode? expireMode, TimeSpan? timeout = null) => _cache.Put(CreateCacheItem(key, value, expireMode, timeout)); public TValue Update(string key, Func updateValue) => _cache.Update(key, _region, updateValue); public TValue? Get(string key) => _cache.Get(key, _region); public void Expire(string key, DateTime absoluteExpiration) => _cache.Expire(key, _region, absoluteExpiration); public void Expire(string key, TimeSpan slidingExpiration) => _cache.Expire(key, _region, slidingExpiration); public void Expire(string key, ExpireMode? expireMode, TimeSpan? timeout = null) => _cache.Expire(key, _region, SwitchExpireMode(expireMode), timeout ?? TimeSpan.FromMinutes(10)); public TValue AddOrUpdate(string key, TValue addValue, Func updateValue, ExpireMode? expireMode = ExpireMode.None, TimeSpan? timeout = null) => _cache.AddOrUpdate(CreateCacheItem(key, addValue, expireMode, timeout), updateValue); public TValue GetOrAdd(string key, TValue value, ExpireMode? expireMode, TimeSpan? timeout = null) => _cache.GetOrAdd(key, _region, (k, r) => CreateCacheItem(key, value, expireMode, timeout)).Value; public TValue GetOrAdd(string key, Func valueFactory, ExpireMode? expireMode, TimeSpan? timeout = null) => _cache.GetOrAdd(key, _region, (k, r) => CreateCacheItem(key, valueFactory(key), expireMode, timeout)).Value; public bool TryGetOrAdd(string key, Func valueFactory, out TValue? value, ExpireMode? expireMode, TimeSpan? timeout = null) { var result = _cache.TryGetOrAdd(key, _region, (k, r) => CreateCacheItem(key, valueFactory(key), expireMode, timeout), out var valueItem); value = result ? valueItem.Value : default; return result; } public bool TryUpdate(string key, Func updateValue, out TValue? value) { return _cache.TryUpdate(key, _region, updateValue, out value); } public bool Remove(string key) => _cache.Remove(key, _region); public bool Exists(string key) => _cache.Exists(key, _region); private static ExpirationMode SwitchExpireMode(ExpireMode? expireMode) => expireMode switch { ExpireMode.None => ExpirationMode.None, ExpireMode.Sliding => ExpirationMode.Sliding, ExpireMode.Absolute => ExpirationMode.Absolute, null => ExpirationMode.None, _ => throw new ArgumentOutOfRangeException(nameof(expireMode), expireMode, null) }; private CacheItem CreateCacheItem(string key, TValue value, ExpireMode? expireMode, TimeSpan? timeout) => new CacheItem(key, _region, value, SwitchExpireMode(expireMode), timeout ?? TimeSpan.FromMinutes(10)); public 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>(); var prefix = options.Value.Prefix; //if (valueType.TryGetCustomAttribute(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; } } }