DefaultTypedCache.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. using System.Collections;
  2. using CacheManager.Core;
  3. using CacheManager.Core.Internal;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.Extensions.Options;
  6. using XF.Domain.Cache;
  7. namespace CallCenter.CacheManager
  8. {
  9. public class DefaultTypedCache<TValue> : ITypedCache<TValue>
  10. where TValue : class
  11. {
  12. private readonly ICacheManager<TValue> _cache;
  13. private readonly IServiceScopeFactory _serviceScopeFactory;
  14. private readonly string _region;
  15. public DefaultTypedCache(ICacheManager<TValue> cache, IServiceScopeFactory serviceScopeFactory)
  16. {
  17. _cache = cache;
  18. _serviceScopeFactory = serviceScopeFactory;
  19. _region = CreateRegion();
  20. }
  21. public bool Add(string key, TValue value, ExpireMode? expireMode = ExpireMode.None, TimeSpan? timeout = null) =>
  22. _cache.Add(CreateCacheItem(key, value, expireMode, timeout));
  23. public void Put(string key, TValue value, ExpireMode? expireMode, TimeSpan? timeout = null) =>
  24. _cache.Put(CreateCacheItem(key, value, expireMode, timeout));
  25. public TValue Update(string key, Func<TValue, TValue> updateValue) => _cache.Update(key, _region, updateValue);
  26. public TValue? Get(string key) => _cache.Get<TValue>(key, _region);
  27. public void Expire(string key, DateTime absoluteExpiration) => _cache.Expire(key, _region, absoluteExpiration);
  28. public void Expire(string key, TimeSpan slidingExpiration) => _cache.Expire(key, _region, slidingExpiration);
  29. public void Expire(string key, ExpireMode? expireMode, TimeSpan? timeout = null) =>
  30. _cache.Expire(key, _region, SwitchExpireMode(expireMode), timeout ?? TimeSpan.FromMinutes(10));
  31. public TValue AddOrUpdate(string key, TValue addValue, Func<TValue, TValue> updateValue, ExpireMode? expireMode = ExpireMode.None, TimeSpan? timeout = null) =>
  32. _cache.AddOrUpdate(CreateCacheItem(key, addValue, expireMode, timeout), updateValue);
  33. public TValue GetOrAdd(string key, TValue value, ExpireMode? expireMode, TimeSpan? timeout = null) =>
  34. _cache.GetOrAdd(key, _region, (k, r) => CreateCacheItem(key, value, expireMode, timeout)).Value;
  35. public TValue GetOrAdd(string key, Func<string, TValue> valueFactory, ExpireMode? expireMode, TimeSpan? timeout = null) =>
  36. _cache.GetOrAdd(key, _region, (k, r) => CreateCacheItem(key, valueFactory(key), expireMode, timeout)).Value;
  37. public bool TryGetOrAdd(string key, Func<string, TValue> valueFactory, out TValue? value, ExpireMode? expireMode, TimeSpan? timeout = null)
  38. {
  39. var result = _cache.TryGetOrAdd(key,
  40. _region,
  41. (k, r) => CreateCacheItem(key, valueFactory(key), expireMode, timeout),
  42. out var valueItem);
  43. value = result ? valueItem.Value : default;
  44. return result;
  45. }
  46. public bool TryUpdate(string key, Func<TValue, TValue> updateValue, out TValue? value)
  47. {
  48. return _cache.TryUpdate(key, _region, updateValue, out value);
  49. }
  50. public bool Remove(string key) => _cache.Remove(key, _region);
  51. public bool Exists(string key) => _cache.Exists(key, _region);
  52. private static ExpirationMode SwitchExpireMode(ExpireMode? expireMode) =>
  53. expireMode switch
  54. {
  55. ExpireMode.None => ExpirationMode.None,
  56. ExpireMode.Sliding => ExpirationMode.Sliding,
  57. ExpireMode.Absolute => ExpirationMode.Absolute,
  58. null => ExpirationMode.None,
  59. _ => throw new ArgumentOutOfRangeException(nameof(expireMode), expireMode, null)
  60. };
  61. private CacheItem<TValue> CreateCacheItem(string key, TValue value, ExpireMode? expireMode, TimeSpan? timeout) =>
  62. new CacheItem<TValue>(key, _region, value, SwitchExpireMode(expireMode), timeout ?? TimeSpan.FromMinutes(10));
  63. public string CreateRegion()
  64. {
  65. var valueType = typeof(TValue);
  66. //if (valueType.IsGenericType)
  67. //{
  68. // throw new NotSupportedException("TCachedValue can not be a Generic Type");
  69. //}
  70. //if (valueType == typeof(string))
  71. //{
  72. // throw new NotSupportedException("TCachedValue can not be a string");
  73. //}
  74. if (string.IsNullOrWhiteSpace(valueType.FullName))
  75. {
  76. throw new NotSupportedException("FullName of type TCachedValue can not be null");
  77. }
  78. using var scope = _serviceScopeFactory.CreateScope();
  79. var options = scope.ServiceProvider.GetRequiredService<IOptionsSnapshot<CacheOptions>>();
  80. var prefix = options.Value.Prefix;
  81. //if (valueType.TryGetCustomAttribute<CacheAttribute>(false, out var attr))
  82. //{
  83. // if (!string.IsNullOrEmpty(attr.Region))
  84. // {
  85. // return attr.Region;
  86. // }
  87. //}
  88. string region;
  89. if (valueType.IsGenericType && valueType.GetInterfaces().Any(d => d == typeof(IEnumerable)))
  90. {
  91. region = "Collection";
  92. }
  93. else
  94. {
  95. region = valueType.FullName.Replace('.', ':');
  96. }
  97. if (!string.IsNullOrEmpty(prefix))
  98. {
  99. prefix += ':';
  100. if (!region.StartsWith(prefix))
  101. {
  102. region = prefix + region;
  103. }
  104. }
  105. return region;
  106. }
  107. }
  108. }