Autofac Single Instance с обработчиками событий - PullRequest
0 голосов
/ 11 сентября 2018

У меня есть класс кэша, который зарегистрирован как один экземпляр в Autofac. Всякий раз, когда я очищаю кеш, я вызываю метод ExecuteCacheCleared();

Класс кеша выглядит так

public IEnumerable<ICacheCleared> _cacheCleared { get; private set; }

public CacheService(IEnumerable<ICacheCleared> cacheCleared) : ICacheService
{
    _cacheCleared = cacheCleared;
}

private void ExecuteCacheCleared()
{
    if (_cacheCleared != null)
    {
        foreach (var cacheCleared in _cacheCleared)
        {
            cacheCleared.EntityCacheChanged();
        }
    }
}

У меня есть несколько конкретных реализаций ICacheCleared, которые вызываются при вызове ExecuteCacheCleared.

Итак, в настоящее время я регистрирую биты в autofac следующим образом:

builder.RegisterType<CacheService>().As<ICacheService>().SingleInstance();
builder.RegisterType<CacheCleared>().As<ICacheCleared>().InstancePerRequest();

С учетом вышеизложенного я получаю ошибку (которую я получаю), поскольку SingleInstance не будет работать с InstancePerRequest, но в моем конкретном классе CacheCleared я также внедряю другие зависимости, которые должны быть InstancePerRequest.

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

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Не совсем понятно, какова цель вашего дизайна. Я использую autofac и имею кеши, которые создаются для каждого запроса, а другие - для одного экземпляра. Обычно запросы должны быть недолговечными, все, что кэшируется для каждого запроса, должно быть моментальным снимком на момент запроса.

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

Во всяком случае, я думаю, что ответ может быть очень простым. ICacheService также должен быть InstancePerRequest или ICacheCleared должен быть одним экземпляром.

В качестве альтернативы вы должны разбить структуру своих кэшей так, чтобы вы отделяли кэши, созданные для каждого запроса, от кэшей, которые создаются в одном экземпляре. т.е. ICacheService , который имеет коллекцию ICacheCleared и IRequestCacheService , который имеет коллекцию IRequestCacheCleared объектов.

Вы можете внедрить отдельные экземпляры объектов в объекты, созданные для каждого запроса, но не наоборот. Поэтому, если вам нравится, IRequestCacheService можно также внедрить с помощью ICacheService и вызвать ExecuteCacheCleared на ICacheService при ExecuteCacheCleared вызывается на IRequestCacheService .

0 голосов
/ 11 сентября 2018

То, что вы пытаетесь сделать, будет невозможно, если взять зависимость от IEnumerable<>. Этот тип отношения предназначен для поддержки нескольких реализаций службы , а не для разрешения всех экземпляров.

Я не знаю ни одного способа сделать то, что вы пытаетесь сделать OOTB. Это довольно эзотерический и сложный сценарий. Лучший способ, который я могу придумать, - это инвертировать элемент управления: требовать, чтобы ваши ICachedCleared реализации зависели от ICacheService. В свою очередь, укажите ICacheService метод, подобный AddNotifier(ICacheCleared), который можно было бы вызвать из конструктора (если он дешевый - я настоятельно рекомендую сделать его дешевым) или при первом использовании (если он дорогой - например, возвращает Task ).

AddNotifier() добавит каждый в коллекцию, которая будет затем вызываться из ExecuteCacheCleared().

Это будет довольно сложно, потому что вы должны быть ОЧЕНЬ осторожны с этим кодом в многопоточной среде - в которой вы наверняка находитесь, поскольку вы используете InstancePerRequest(). Кроме того, вам нужно будет найти способ удаления всех тех случаев, когда запрос завершен (используйте коллекцию WeakReferences? Make ICacheCleared внедрить IDisposable и назовите ICacheService.Remove() при утилизации?). И, вероятно, многие другие вопросы, которые я не рассматривал.

Сложность этого достаточно высока, так что вы можете потратить некоторое время и пересмотреть сам дизайн, прежде чем отправиться в кроличью нору.

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...