Создаю приложение WinForms
. В главном классе Form1 имею объект MemoryCache cache
.
В остальных классах необходимо узнать, есть ли уже запись по данному ключу, если есть - получить, если нет - рассчитать значение, добавить в кэш и присвоить значение к списку List<double
Как лучше такое реализовать?
Грубо говоря :
1. Есть похожий ключ в кэше?
2. Нет - делаем расчет и добавляем в кэш, есть - берем из кэша и не делаем расчет.
Как это выглядит в коде?
Заранее спасибо за помощь.
Как бы это сделал я:
Определяем интерфейс для источника данных
public interface IDataProvider
{
List<double> GetData();
}
Обычный наш источник данных:
internal class MyDataProvider : IDataProvider
{
public List<double> GetData()
{
Console.WriteLine("Provider called");
return Enumerable.Range(0, 100).Select(x=>Convert.ToDouble(x)).ToList();
}
}
Далее, пишем кеширующий декоратор
internal class MyCachedDataProvider : IDataProvider
{
IDataProvider _inner;
ICache<List<double>> _cache;
private string key = Guid.NewGuid().ToString();
private object _locker = new object();
public MyCachedDataProvider(IDataProvider inner, ICache<List<double>> cache)
{
_inner = inner;
_cache = cache;
}
public List<double> GetData()
{
var result = _cache.Get(key);
if (result == null)
{
// лочим только чтобы 2 раза не генерить данные в многопоточном сценарии.
lock (_locker)
{
result = _cache.Get(key);
if (result == null)
{
result = _inner.GetData();
_cache.Add(key, result);
}
}
}
return result;
}
}
Соответственно, нам надо кеш. Заводим интерфейс
public interface ICache<T>
{
void Add(string key, T value);
T Get(string key);
}
Наивная реализация
internal class Cache<T> : ICache<T>
{
MemoryCache cache = new MemoryCache(Guid.NewGuid().ToString());
TimeSpan expireTime;
public Cache()
{
expireTime = TimeSpan.FromSeconds(2);
//cache = MemoryCache.Default;
}
public void Add(string key, T value)
{
var cacheItem = new CacheItem(key, value);
// Ваши политики протухания кеша
var policy = new CacheItemPolicy() { SlidingExpiration = expireTime };
//var policy = new CacheItemPolicy() {AbsoluteExpiration = DateTime.Now.Add(expireTime)};
cache.Add(cacheItem, policy);
}
public T Get(string key)
{
var item = cache.GetCacheItem(key);
var ii = cache[key];
return (T)cache.Get(key);
}
}
Как это можно использовать:
var dataProvider = new MyCachedDataProvider( new MyDataProvider(), new Cache<List<double>>());
for (var i = 0; i < 1000; i++)
{
dataProvider.GetData();
}
Как передать в другой класс
var form = new MyForm(dataProvider);
// Где форма
public class MyForm : Form
{
IDataProvider _dataProvider ;
public MyForm(IDataProvider dataProvider)
{
_dataProvider = dataProvider;
}
}
Как передать в метод
var anotherform = new MyAnotherForm();
anotherform.SomethingToDo(dataProvider);
// Где форма
public class MyAnotherForm : Form
{
public void SomethingToDo(IDataProvider dataProvider)
{
for (var i = 0; i < 1000; i++)
{
dataProvider.GetData();
}
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
всем привет! ситуация следующая - мне нужно каждый час запускать exe-файл или скрипт mainjs в виндовс 7,8,10
Используя phantomjs получаю страничкуКак сделать клик по элементу
Есть функция, которая переводит длину песни в минуты и секунды(изначально дли в секундах)