#if NETCOREAPP using Microsoft.Extensions.Caching.Memory; #endif using Kit.Helpers.Cache; using System; using System.Collections.Generic; namespace Kit.Helpers.Repository { public abstract class DictionaryRepositoryLazy : IDictionaryRepository where TEntity : IPersistentKey { private readonly string _cacheKey; private readonly ICacheProvider _cacheProvider; #if NETCOREAPP private readonly MemoryCacheEntryOptions _cacheOptions = new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1), Priority = CacheItemPriority.Normal }; #elif NETFRAMEWORK private readonly CacheSetProperties _cacheOptions = new CacheSetProperties { DurationSeconds = 3600, EnableCaching = true }; #endif private readonly object _lockObject = new object(); public DictionaryRepositoryLazy(ICacheProvider cacheProvider, string cacheKey) { _cacheProvider = cacheProvider; _cacheKey = cacheKey; } // лучше сделать абстрактным protected abstract IEnumerable GetData(); protected abstract TEntity GetData(TKey key); public IDictionary Select() { IDictionary values = null; if (_cacheKey.IsNullOrEmpty()) { throw new ArgumentNullException("Не задан ключ кеширования для репозитория: {0}".ApplyFormat(this.GetType().ToString())); } lock (_lockObject) { if (_cacheProvider.Contains(_cacheKey)) { values = (IDictionary)_cacheProvider.GetCacheData(_cacheKey); return values; } IEnumerable data = this.GetData(); values = new Dictionary(); // добавить обработку дубликатов foreach (var item in data) { TKey key = item.PersistentKey; if (values.ContainsKey(key)) { throw new Exception("Элемент с ключом {0} уже добавлен в коллекцию".ApplyFormat(key)); } values.Add(item.PersistentKey, item); } _cacheProvider.SetCacheData(_cacheKey, values, _cacheOptions); return values; } } public TEntity Get(TKey key) { lock (_lockObject) { IDictionary values = this.Select(); if (values.ContainsKey(key)) { return values[key]; } TEntity entity = this.GetData(key); if (entity == null) { return default(TEntity); } values.Add(key, entity); _cacheProvider.SetCacheData(_cacheKey, values, _cacheOptions); return entity; } } public void ClearCache() { _cacheProvider.PurgeCacheItems(_cacheKey); } } }