Как определить и исключить исключения из MemoryCache при использовании с Lazy <T>? - PullRequest
0 голосов
/ 13 марта 2019

Я использую следующий шаблон с MemoryCache:

public static T GetFromCache<T>(string key, Func<T> valueFactory) {
    var newValue = new Lazy<T>(valueFactory);
    var oldValue = (Lazy<T>)cache.AddOrGetExisting(key, newValue, new CacheItemPolicy());
    return (oldValue ?? newValue).Value;
}

И назовите это:

var v = GetFromCache<Prop>(request.Key, () => LongCalc());

Это работает достаточно хорошо. Однако, когда LongCalc выдает исключение, cache.AddOrGetExisting сохраняет исключение в кеш.

Я пытаюсь определить, когда это произойдет:

if (oldValue != null && oldValue.Value.GetType() == typeof(Exception)) {
  cache.Remove(key, CacheEntryRemovedReason.Evicted);
}

но простой вызов oldValue.Value вызывает исключение.

Как я могу определить, содержит ли объект oldValue исключение, и обработать его соответствующим образом?

1 Ответ

1 голос
/ 13 марта 2019

Это неправильный подход.Он никогда не работает с отложенной оценкой, особенно если вам придется поднять его в многопоточную среду один раз.Передайте (в идеале, чистый - т.е. не сохраняющий состояние) обратный вызов Action<Exception> в качестве необязательного параметра и убедитесь, что существует разумная, но достаточно универсальная реализация по умолчанию.

Или, по крайней мере, укажите свой пользовательский ExceptionAwareLazy<T>, который будет содержать соответствующий флаг.Такое решение будет намного хуже, однако никакие асинхронные обратные вызовы не будут беспокоить вас.

PS ReactiveExtensions - хорошие примеры подхода, который я предложил.Вы можете легко обернуть ваше решение в TaskCompletionSource и придерживаться известного async/await.

...