Этот репозиторий содержит четыре библиотеки, которые концептуально связаны тем, что все они связаны с LINQ над последовательностями действий:
Реактивные расширения для .NET, также известные как Rx.NET или Rx (System.Reactive): библиотека для событийно-ориентированного программирования с компонуемой декларативной моделью.
AsyncRx.NET (экспериментальная предварительная версия) (System.Reactive.Async): экспериментальная реализация Rx для IAsyncObservable<T>
предлагающая более глубокую поддержку async
/ await
Интерактивные расширения для .NET, также известные как Ix (System.Interactive): расширенные операторы LINQ для IAsyncEnumerable
и IEnumerable
LINQ для IAsyncEnumerable
(System.Linq.Async): реализует стандартные операторы LINQ для IAsyncEnumerable
Каждый из них будет описан позже в этом README.
Реактивное программирование обеспечивает ясность, когда нашему коду необходимо реагировать на события. Библиотеки Rx.NET были разработаны, чтобы позволить облачным приложениям обрабатывать текущие данные надежным и предсказуемым способом.
Мы написали БЕСПЛАТНУЮ книгу, в которой объясняются жизненно важные абстракции, лежащие в основе Rx, и показано, как использовать мощные и обширные функциональные возможности, встроенные в библиотеки Rx.NET.
Основанная на книге Ли Кэмпбелла 2010 года (любезно подаренной проекту), она была переписана, чтобы привести ее в соответствие с Rx.NET v6.0, .NET 8.0 и современными сценариями использования облачных технологий, такими как Интернет вещей и реальные технологии. обработка данных временного потока.
Введение в Rx.NET доступно в Интернете, на GitHub, в форматах PDF и EPUB.
Канал | прием | Асинкркс | IX | System.Linq.Async |
---|---|---|---|---|
NuGet.org | ||||
Предварительная версия NuGet.org (если новее, чем версия) | ||||
Строить | Построен как часть Ix | |||
Лазурный Артефакты | ||||
История выпусков | История выпусков | История выпусков | История выпусков |
Для ночных сборок настройте NuGet на использование этого канала: https://pkgs.dev.azure.com/dotnet/Rx.NET/_packaging/RxNet/nuget/v3/index.json
.
Следите за нами на канале #rxnet по адресу https://reactivex.slack.com/.
В эпоху цифровых технологий потоки данных в реальном времени становятся повсеместными. Финансовые приложения зависят от быстрого реагирования на своевременную информацию. Компьютерные сети всегда могли предоставить обширную информацию о своем состоянии и работе. Коммунальные компании, такие как поставщики воды, имеют огромное количество устройств, контролирующих их работу. Фреймворки пользовательского интерфейса и создания игр очень подробно сообщают о взаимодействиях с пользователем. Автофургоны постоянно сообщают о своем прогрессе. Самолеты обеспечивают телеметрию производительности, чтобы обнаружить потенциальные проблемы с обслуживанием до того, как они станут серьезными, и автомобили теперь начинают делать то же самое. Многие из нас носят или носят с собой устройства, которые отслеживают нашу физическую активность и даже жизненные показатели. А улучшения в машинном обучении обогатили понимание, которое можно получить из постоянно растущего объема и разнообразия живых данных.
Но, несмотря на столь широкое распространение, прямые информационные потоки всегда были чем-то вроде человека второго сорта. Почти все языки программирования имеют некий врожденный способ работы со списками данных (например, массивами), но эти механизмы склонны предполагать, что соответствующие данные уже находятся в памяти и готовы к работе с ними. Чего не хватает, так это живости — того факта, что источник информации может создавать новые данные в любой момент по своему собственному графику.
Rx поднимает поддержку живых потоков информации до того же уровня, которого мы ожидаем от таких вещей, как массивы. Вот пример:
var bigTrades = из торговли в сделках, где trade.Volume > 1_000_000 выберите сделку;
При этом используется функция LINQ C# для фильтрации trades
до тех объектов, объем которых превышает один миллион. Этот синтаксис выражения запроса — это всего лишь сокращение для вызовов методов, поэтому мы могли бы написать его и так:
var bigTrades = trades.Where(trade => trade.Volume > 1_000_000);
Точное поведение этих двух (эквивалентных) фрагментов кода зависит от типа trades
. Если бы это был IEnumerable<Trade>
, тогда этот запрос просто перебирал бы список, а bigTrades
был бы перечислимой последовательностью, содержащей только соответствующие объекты. Если бы trades
были объектом, представляющим таблицу базы данных (например, Entity Framework DbSet), это было бы преобразовано в запрос к базе данных. Но если мы используем Rx, trades
были бы IObservable<Trade>
, объектом, сообщающим о текущих событиях по мере их возникновения. И bigTrades
также будет IObservable<Trade>
, сообщая только о сделках с объемом более миллиона. Мы можем предоставить Rx обратный вызов, который будет вызываться каждый раз при обнаружении наблюдаемого источника. есть кое-что для нас:
bigTrades.Subscribe(t => Console.WriteLine($"{t.Symbol}: торговля объемом {t.Volume}"));
Двумя ключевыми особенностями Rx являются:
четко определенный способ представления и обработки живых последовательностей данных ( IObservable<T>
)
набор операторов (таких как только что показанный оператор Where
), позволяющий декларативно выражать логику обработки событий
Rx особенно успешно применяется в пользовательских интерфейсах. (Это справедливо и за пределами .NET: RxJS является ответвлением Rx от JavaScript и очень популярен в коде пользовательского интерфейса.) https://github.com/reactiveui/reactiveui широко использует Rx для поддержки Разработка пользовательского интерфейса .NET.
Ян Гриффитс представил краткий 60-минутный обзор реактивных расширений для .NET на встрече dotnetsheff в 2020 году. Дополнительные видеоролики доступны в плейлисте Rx.
Хотя Rx — это естественный способ моделирования асинхронных процессов, его первоначальная конструкция предполагала, что код, действующий на уведомления, будет выполняться синхронно. Это связано с тем, что дизайн Rx предшествует функциям языка C# async
/ await
. Поэтому, хотя Rx предлагает адаптеры, которые могут конвертировать между IObservable<T>
и Task<T>
, в некоторых случаях async
была невозможна.
AsyncRx.Net снимает это ограничение, определяя IAsyncObservable<T>
. Это позволяет наблюдателям использовать асинхронный код. Например, если бы bigTrades
был IAsyncObservable<Trade>
мы могли бы написать следующее:
bigTrades.Subscribe(async t => await bigTradeStore.LogTradeAsync(t));
AsyncRx.Net в настоящее время находится в предварительной версии.
Rx определяет все стандартные операторы LINQ, доступные для других поставщиков, но также добавляет множество дополнительных операторов. Например, он определяет Scan
, который выполняет ту же базовую обработку, что и стандартный оператор Aggregate
, но вместо того, чтобы выдавать один результат после обработки каждого элемента, он создает последовательность, содержащую агрегированное значение, после каждого отдельного шага. (Например, если агрегируемая операция — сложение, Aggregate
вернет общую сумму как один выходной результат, тогда как Scan
выдаст промежуточный итог для каждого входного параметра. Учитывая последовательность [1,2,3]
, Aggregate((a, x) => a + x)
выдает только 6
, тогда как Scan
выдает [1,3,6]
.)
Некоторые дополнительные операторы, определенные Rx, полезны только при работе с событиями. Но некоторые из них применимы к последовательностям любого типа. Таким образом, интерактивные расширения (сокращенно Ix) определяют реализации IEnumerable<T>
. Ix по сути является расширением LINQ to Objects, добавляющим множество дополнительных операторов. (Его полезность подтверждается тем фактом, что в библиотеки времени выполнения .NET со временем были добавлены некоторые операторы, которые раньше были доступны только в Ix. Например, в .NET 6 добавлены MinBy
и MaxBy
, операторы, ранее определенные только IX.)
Эта библиотека называется «Интерактивные расширения», потому что «Интерактивный» в некотором смысле противоположен «Реактивному». (Имя не относится к взаимодействию с пользователем.)
IAsyncEnumerable
( System.Linq.Async
) Одной из функций, впервые предложенных Ix, была асинхронная версия IEnumerable<T>
. Это еще один пример функции, настолько полезной, что в конечном итоге она была добавлена в библиотеки времени выполнения .NET: в .NET Core 3.0 появился IAsyncEnumerable<T>
, а в связанной версии C# (8.0) добавлена встроенная поддержка этого интерфейса с его конструкцией await foreach
.
Хотя в .NET Core 3.0 определен IAsyncEnumerable<T>
, в него не была добавлена соответствующая реализация LINQ. В то время как IEnumerable<T>
поддерживает все стандартные операторы, такие как Where
, GroupBy
и SelectMany
, .NET не имеет встроенных реализаций ни одного из них для IAsyncEnumerable<T>
. Однако компания Ix с самого начала предоставила операторы LINQ для своей прототипной версии IAsyncEnumerable<T>
, поэтому при выпуске .NET Core 3.0 было относительно простой задачей обновить все существующие операторы LINQ для работы с новым официальным IAsyncEnumerable<T>
.
Таким образом, был создан пакет NuGet System.Linq.Async, предоставляющий реализацию LINQ to Objects для IAsyncEnumerable<T>
, соответствующую уже встроенной в .NET для IEnumerable<T>
.
Поскольку весь соответствующий код уже был частью проекта Ix (причем IAsyncEnumerable<T>
также изначально был определен в этом проекте), пакет NuGet System.Linq.Async создается как часть проекта Ix.
Некоторые из лучших способов внести свой вклад — это пробовать что-то, сообщать об ошибках и участвовать в обсуждениях дизайна.
Клонируйте исходники: git clone https://github.com/dotnet/reactive
Сборка, тестирование и отладка исходников
Как внести свой вклад
Запросы на включение: открытые/закрытые
Ищете, над чем поработать? Список возможных проблем — отличное место для начала.
В этом проекте принят кодекс поведения, адаптированный на основе Соглашения с участниками, чтобы прояснить ожидаемое поведение в нашем сообществе. Этот кодекс поведения был принят во многих других проектах. Дополнительную информацию см. в Кодексе поведения.
Этот проект является частью .NET Foundation наряду с другими проектами, такими как .NET Runtime. .NET Foundation предоставляет этому проекту инфраструктуру DevOps для компиляции, тестирования, подписания и упаковки этого сложного решения, которое скачали более 100 миллионов раз. Он также обеспечивает консервацию, позволяющую проекту передаваться от сопровождающего к сопровождающему, обеспечивая непрерывность работы сообщества.
Люди, которые в настоящее время поддерживают Rx:
Ян Гриффитс Хоув, Великобритания Блог Йена на endjin.com | Ховард ван Ройен Винчестер, Великобритания Блог Ховарда на endjin.com |
Rx существует уже около полутора десятилетий, поэтому мы во многом обязаны его создателям и многим людям, которые работали над ним с тех пор. Полный список см. в AUTHORS.txt.
В рамках .NET Conf 2023 Ян Гриффитс представил обновленную информацию об усилиях по модернизации Rx.NET для версии 6.0 и планах по модернизации версии 7.0.
Для получения дополнительной информации см. следующие обсуждения:
Будущая упаковка Rx.NET
План высокого уровня Rx.NET v6.0 и v7.0
Мы составили дорожную карту, объясняющую наши среднесрочные планы дальнейшего развития Rx. Эта диаграмма иллюстрирует наш взгляд на платформы, на которых используется Rx, и запланированные жизненные циклы поддержки для этих различных целей: