Подтвердить что ты не робот

Кэшировать атрибут для метода?

Возможно, это сновидение, но возможно ли создать атрибут, который кэширует вывод функции (например, в HttpRuntime.Cache) и возвращает значение из кеша вместо фактического выполнения функции, когда параметры функции одинаковы?

Когда я говорю функцию, я говорю о любой функции, независимо от того, извлекает ли она данные из БД, добавляет ли он два целых числа или выплескивает ли содержимое файл. Любая функция.

4b9b3361

Ответ 1

Лучше всего Postsharp. Я понятия не имею, есть ли у них то, что вам нужно, но это, безусловно, стоит проверить. Кстати, не забудьте опубликовать ответ здесь, если найдете его.

EDIT: также, googling "кеширование postsharp" дает некоторые ссылки, например: Кэширование с С#, AOP и PostSharp

UPDATE: Я недавно наткнулся на эту статью: Представление кэширования на основе атрибутов. Он описывает библиотеку на основе postharp на http://cache.codeplex.com/, если вы все еще ищете решение.

Ответ 2

У меня есть одна и та же проблема - у меня в моем приложении много дорогих методов, и мне необходимо кэшировать эти результаты. Некоторое время назад я просто скопировал аналогичный код, но потом решил отказаться от этой логики из своего домена. Вот как я это делал раньше:

    static List<News> _topNews = null;
    static DateTime _topNewsLastUpdateTime = DateTime.MinValue;
    const int CacheTime = 5;  // In minutes

    public IList<News> GetTopNews()
    {
        if (_topNewsLastUpdateTime.AddMinutes(CacheTime) < DateTime.Now)
        {
            _topNews = GetList(TopNewsCount);
        }

        return _topNews;
    }

И вот как я могу написать сейчас:

    public IList<News> GetTopNews()
    {
        return Cacher.GetFromCache(() => GetList(TopNewsCount));
    }

Cacher - это простой вспомогательный класс, вот он:

public static class Cacher
{
    const int CacheTime = 5;  // In minutes

    static Dictionary<long, CacheItem> _cachedResults = new Dictionary<long, CacheItem>();

    public static T GetFromCache<T>(Func<T> action)
    {
        long code = action.GetHashCode();

        if (!_cachedResults.ContainsKey(code))
        {
            lock (_cachedResults)
            {
                if (!_cachedResults.ContainsKey(code))
                {
                    _cachedResults.Add(code, new CacheItem { LastUpdateTime = DateTime.MinValue });
                }
            }
        }

        CacheItem item = _cachedResults[code];
        if (item.LastUpdateTime.AddMinutes(CacheTime) >= DateTime.Now)
        {
            return (T)item.Result;
        }

        T result = action();

        _cachedResults[code] = new CacheItem
        {
            LastUpdateTime = DateTime.Now,
            Result = result
        };

        return result;
    }
}


class CacheItem
{
    public DateTime LastUpdateTime { get; set; }
    public object Result { get; set; }
}

Несколько слов о Кахере. Вы можете заметить, что я не использую Monitor.Enter() (lock (...)) при вычислении результатов. Это связано с тем, что копирование указателя CacheItem (return (T) _cachedResults [code].Result; line) - это поточно-безопасная операция - выполняется только одним ударом. Также нормально, если более одного потока будет изменять этот указатель одновременно - все они будут действительны.

Ответ 3

Вы можете добавить словарь в свой класс, используя строку с запятой, включая имя функции в качестве ключа, и результат в качестве значения. Затем, когда ваши функции могут проверять словарь на наличие этого значения. Сохраните словарь в кеше, чтобы он существовал для всех пользователей.

Ответ 4

AFAIK, честно говоря, нет.

Но это было бы обязательным условием для реализации в рамках, чтобы оно работало в целом для всех при любых обстоятельствах. Во всяком случае, вы могли бы адаптировать что-то вполне достаточное для удовлетворения потребностей просто (где простота относительно потребностей, очевидно) с использованием абстракции, наследования и существующего кэша ASP.NET.

Ответ 5

PostSharp - это ваш единственный магазин для этого, если вы хотите создать атрибут [Cache] (или аналогичный), который вы можете использовать любым способом в любом месте. Раньше, когда я использовал PostSharp, я никогда не мог пройти мимо того, как медленно он сделал мои сборки (это было в 2007 году, поэтому это может быть не актуально больше).

Альтернативным решением является просмотр Render.Partial с помощью ASP.NET MVC в сочетании с OutputCaching. Это отличное решение для обслуживания html для областей виджетов/страниц.

Другим решением, которое было бы с MVC, было бы реализовать ваш атрибут [Cache] как ActionFilterAttribute. Это позволит вам принять метод контроллера и пометить его кешированием. Он будет работать только для методов контроллера, так как магия АОП может возникать только с ActionFilterAttributes во время конвейера MVC.

Реализация AOP через ActionFilterAttribute превратилась в решение goto для моего магазина.

Ответ 6

Если вам не нужна настройка атрибута, но вы принимаете конфигурацию кода, возможно, MbCache - это то, что вы ищете?