Как удалить все объекты (reset) из IMemoryCache в ядре ASP.NET

Я могу найти метод remove для удаления объекта из IMemoryCache по его ключу. Есть ли способ reset весь кеш и удалить все объекты?

Edit:

Как очистить MemoryCache? Метод Dispose, предоставленный в ссылке, дает мне исключение в asp.net 5. ObjectDisposedException: Cannot access a disposed object. Object name: 'Microsoft.Extensions.Caching.Memory.MemoryCache'.

Ответ 1

https://docs.microsoft.com/en-us/aspnet/core/performance/caching/memory Раздел Зависимости кэша

Использование CancellationTokenSource позволяет удалить несколько записей кэша в качестве группы

Этот код работал для меня:

public class CacheProvider 
{
    private static CancellationTokenSource _resetCacheToken = new CancellationTokenSource();
    private readonly IMemoryCache _innerCache;

    /* other methods and constructor removed for brevity */

    public T Set<T>(object key, T value) 
    {
        /* some other code removed for brevity */
        var options = new MemoryCacheEntryOptions().SetPriority(CacheItemPriority.Normal).SetAbsoluteExpiration(typeExpiration);
        options.AddExpirationToken(new CancellationChangeToken(_resetCacheToken.Token));

        _innerCache.Set(CreateKey(type, key), value, options);

        return value;
    }

    public void Reset()
    {
        if (_resetCacheToken != null && !_resetCacheToken.IsCancellationRequested && _resetCacheToken.Token.CanBeCanceled)
        {
            _resetCacheToken.Cancel();
            _resetCacheToken.Dispose();
        }

        _resetCacheToken = new CancellationTokenSource();
    }
}

Ответ 2

Ответ на RC1 заключается в том, что вы не можете сделать это из коробки из того, что я прочитал и сказали (я читал в GitHub, что, возможно, есть способ создать триггеры, чтобы облегчить это, что происходит),

В настоящее время вам предоставляются Get, Set и Remove. Я вижу ваши варианты как:

  • Создайте обертку диспетчера кэша, которая будет отслеживать все ваши ключи, и затем вы сможете удалить эти элементы навалом, если хотите. Я не влюблен в это, но это сработает. Конечно, если вы не контролируете добавление, в кеше могут быть вещи, о которых вы не знаете (вы могли бы сравнить свой счет с ним, чтобы посмотреть). Если вы нажмете IMemoryCache в качестве MemoryCache, вы можете получить открытое свойство Count.
  • Выполните сборку и выведите Ключи и/или добавьте метод удаления этих элементов. Существует основной словарь, содержащий ключи. Я сделал это, скомпилировал его, создав для него пакет Nuget, а затем заменил версию RC1, чтобы увидеть, могу ли я (и это сработало). Не уверен, что это правильный путь, но вот фиксация моей вилки, я просто добавил свойство только для чтения, где я сбросил ключи в список объектов (ключи хранятся как объекты). Как и в прошлых реализациях MemoryCache, если вы открыли ключи, они могут быть устаревшими после их сброса, но если вы просто используете их для очистки всех, то это не имеет значения.

https://github.com/blakepell/Caching/commit/165ae5ec13cc51c44a6007d6b88bd9c567e1d724

Я опубликовал эту проблему вчера вечером, пытаясь выяснить, есть ли хороший способ проверить, что конкретно в кеше (спрашивайте, почему у нас нет способа). Если вы не спросите, вы никогда не узнаете, имеет ли это значение, поэтому я понял, почему нет.

https://github.com/aspnet/Caching/issues/149

Ответ 3

Есть много хаков, чтобы сделать это. Если у вас есть правильный IMemoryCache, вы можете использовать Compact(1.0), иначе этот хак работает:

Этот код будет работать (проверено в модульных тестах и на производстве на .NET core 2.2):

PropertyInfo prop = cache.GetType().GetProperty("EntriesCollection", BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic | BindingFlags.Public);
object innerCache = prop.GetValue(cache);
MethodInfo clearMethod = innerCache.GetType().GetMethod("Clear", BindingFlags.Instance | BindingFlags.Public);
clearMethod.Invoke(innerCache, null);

Ответ 4

Мое решение состояло в том, чтобы установить новую дату истечения срока действия для всех элементов в кэше равной 1 миллисекунде. Затем они истекли и, следовательно, очистить кэш.

Ответ 5

Мое решение состояло в том, чтобы создать оболочку, которая повторно отображает существующие несколько методов и добавляет отсутствующий метод, заменив объект MemoryCache новым. Работало просто отлично для меня. Код ниже:

public interface IMyMemoryCache : IMemoryCache
{
    void Reset();
}
public class MyMemoryCache: IMyMemoryCache
{
    IMemoryCache _memoryCache;

    public MyMemoryCache()
    {
        Reset();
    }
    public void Dispose()
    {
        _memoryCache.Dispose();
    }

    public bool TryGetValue(object key, out object value)
    {
        return _memoryCache.TryGetValue(key, out value);
    }

    public ICacheEntry CreateEntry(object key)
    {
        return _memoryCache.CreateEntry(key);
    }

    public void Remove(object key)
    {
        _memoryCache.Remove(key);
    }

    public void Reset()
    {
        _memoryCache = new MemoryCache(new MemoryCacheOptions());
    }
}