Правильная реализация в программе MemoryCache

236
30 октября 2017, 20:38

Создаю приложение WinForms. В главном классе Form1 имею объект MemoryCache cache. В остальных классах необходимо узнать, есть ли уже запись по данному ключу, если есть - получить, если нет - рассчитать значение, добавить в кэш и присвоить значение к списку List<double Как лучше такое реализовать? Грубо говоря : 1. Есть похожий ключ в кэше? 2. Нет - делаем расчет и добавляем в кэш, есть - берем из кэша и не делаем расчет. Как это выглядит в коде? Заранее спасибо за помощь.

Answer 1

Как бы это сделал я:

Определяем интерфейс для источника данных

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();
        }
    }
}
READ ALSO
Зачем return после редиректа?

Зачем return после редиректа?

Есть система авторизацииВот её основная часть:

269
нужно каждый час запускать Electron АПКУ на windows

нужно каждый час запускать Electron АПКУ на windows

всем привет! ситуация следующая - мне нужно каждый час запускать exe-файл или скрипт mainjs в виндовс 7,8,10

197
Клик по ссылке с помощью PhantomJS

Клик по ссылке с помощью PhantomJS

Используя phantomjs получаю страничкуКак сделать клик по элементу

324
Проблема с выводом длины песни на экран

Проблема с выводом длины песни на экран

Есть функция, которая переводит длину песни в минуты и секунды(изначально дли в секундах)

240