Управление зависимостями IObservable - PullRequest
0 голосов
/ 10 апреля 2019

У меня есть параметризованная Наблюдаемая, которую я создаю с использованием фабрики, т.е.

// tick when the day changes in a given timezone
IObservable<DateTime> GetInstrumentTzDateRollObservable(string timeZoneName) 

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

Теперь, если есть только один потребитель, все просто - мы просто продолжаем строить конвейер. Но подписчики динамичны, то есть пользователь может открыть новый экран, который будет нуждаться в тех же данных. Кажется, мне нужен способ кеширования наблюдаемых в каждом часовом поясе, чтобы потребитель получал поток из этого кэша, если он есть (GetOrAdd). Простое решение - это, конечно, класс, содержащий словарь этих наблюдаемых.

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

Обновление : в соответствии с просьбой я хочу представить более реалистичный сценарий предполагаемой высокой стоимости генерации элементов наблюдаемого. Надеюсь, это станет понятнее.

Существует база данных, которая содержит данные для всех инструментов. Есть загрузчик, который может получать данные по каждому инструменту. Существует поток уведомлений, который отмечается при обновлении данных. Загрузчику также нужна дата для подготовки загруженных данных. Результат затем представляется в виде наблюдаемого потока:

    IObservable<IntrumentData> GetExpensiveDbDataStreamPerIntrument(string instrumentName)
    {
        // date provider ticks when a day in a given timezone changes prompting us to reload from source
        _dateProvider.GetInstrumentTzDateRollObservable(instrumentName)
            // combine with new data notifications to force a reload
            .CombineLatest(_newDataNotificationObservable.GetNotificationsForInstrument(instrumentName), (date, event) => date)
            .Select(date => _dataLoader.LoadData(instrumentName, date))
            // this has been expensive to load so we want to be able to share the result
            .Replay(1).RefCount();
    }

Итак - как я могу поделиться этими дорогими потоками, когда клиент может подписаться и отказаться от подписки, динамически выбирая инструменты из длинного списка и используя несколько экранов, для которых нужны одни и те же данные инструмента?

...