Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/akarnokd/reactive-extensions
Extensions to the dotnet/reactive library.
https://github.com/akarnokd/reactive-extensions
dotnet extensions reactive rx-dotnet
Last synced: 19 days ago
JSON representation
Extensions to the dotnet/reactive library.
- Host: GitHub
- URL: https://github.com/akarnokd/reactive-extensions
- Owner: akarnokd
- License: apache-2.0
- Created: 2018-05-08T10:37:07.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2023-03-02T04:58:23.000Z (over 1 year ago)
- Last Synced: 2024-10-14T12:26:34.542Z (about 1 month ago)
- Topics: dotnet, extensions, reactive, rx-dotnet
- Language: C#
- Size: 724 KB
- Stars: 50
- Watchers: 6
- Forks: 3
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# reactive-extensions
Travis-CI:
VSTS: [![Build Status](https://dev.azure.com/akarnokd/MyFirstProject/_apis/build/status/7?api-version=5.0-preview.1)](https://akarnokd.visualstudio.com/MyFirstProject/_build/index?definitionId=7)
NuGet:Extensions to the [dotnet/reactive](https://github.com/dotnet/reactive) library.
### Setup
```
Install-Package akarnokd.reactive_extensions -Version 0.0.27-alpha
```### Dependencies
- `NETStandard2.0`
- [`System.Reactive` 4.1.0 or newer](https://www.nuget.org/packages/System.Reactive/).### Table of contents
- `IObservable` support
- [Operators](#operators)
- [Other classes](#other-classes)
- [TestObserver](#testobserver)
- [TestScheduler](#testscheduler)
- New reactive types
- [ICompletableSource](#icompletablesource)
- [CompletableSubject](#completablesubject)
- [ISingleSource](#isinglesource)
- [SingleSubject](#singlesubject)
- [IMaybeSource](#imaybesource)
- [MaybeSubject](#maybesubject)
- [IObservableSource](#iobservablesource)
- [PublishSubject](#publishsubject)
- [CacheSubject](#cachesubject)
- [MonocastSubject](#monocastsubject)## Operators
These operators are available as extension methods on `IObservable` via the
`akarnokd.reactive_extensions.ReactiveExtensions` static class.```cs
using akarnokd.reactive_extensions;
```- Datasources
- [Create](#create)
- [IntervalRange](#intervalrange)
- Side-effecting sequences
- [DoAfterNext](#doafternext)
- [DoAfterTerminate](#doafterterminate)
- [DoFinally](#dofinally)
- [DoOnDispose](#doondispose)
- [DoOnSubscribe](#doonsubscribe)
- Custom asynchronous boundaries
- [ObserveOn](#observeon)
- [ToSerialized](#toserialized)
- Combinators
- [CombineLatest](#combinelatest)
- [ConcatEager](#concateager)
- [ConcatMap](#concatmap)
- [ConcatMapEager](#concatmapeager)
- [ConcatMany](#concatmany)
- [MergeMany](#mergemany)
- [SwitchMany](#switchmany)
- [SwitchMap](#switchmap)
- [WithLatestFrom](#withlatestfrom)
- [Zip](#zip)
- Aggregators
- [Cache](#cache)
- [Collect](#collect)
- Composition
- [Compose](#compose)
- Termination handling
- [Repeat](#repeat)
- [Retry](#retry)
- [SwitchIfEmpty](#switchifempty)
- [UnsubscribeOn](#unsubscribeon)
- Blocking
- [BlockingEnumerable](#blockingenumerable)
- [BlockingSubscribe](#blockingsubscribe)
- [BlockingSubscribeWhile](#blockingsubscribewhile)
- Test support
- [Test](#test)### BlockingEnumerable
Consumes the source observable in a blocking fashion
through an IEnumerable.```cs
var source = Observable.Range(1, 5).SubscribeOn(NewThreadScheduler.Default);foreach (var v in source.BlockingEnumerable()) {
Console.WriteLine(v);
}
Console.WriteLine("Done");
```*Since 0.0.4*
### BlockingSubscribe
Consumes the source observable in a blocking fashion
via callbacks or an observer on the caller thread.Consuming via an `IObservable`:
```cs
var source = Observable.Range(1, 5).SubscribeOn(NewThreadScheduler.Default);var to = new TestObserver();
source.BlockingSubscribe(to);to.AssertResult(1, 2, 3, 4, 5);
```Consuming via `Action` delegates:
```cs
source.BlockingSubscribe(
Console.WriteLine,
Console.WriteLine,
() => Console.WriteLine("Done")
);
```*Since 0.0.4*
See also: [BlockingSubscribeWhile](#blockingsubscribewhile)### BlockingSubscribeWhile
Consumes the source observable in a blocking fashion on
the current thread and relays events to the given callback actions
while the `onNext` predicate returns true.```cs
source.BlockingSubscribe(v => {
Console.WriteLine(v);
return v == 3;
}, Console.WriteLine, () => Console.WriteLine("Done"));
```*Since 0.0.4*
See also: [BlockingSubscribe](#blockingsubscribe)### Cache
Subscribes once to the upstream when the first observer subscribes to the operator, buffers
all upstream events and relays/replays them to current or late observers.```cs
var count = 0;var cached = Observable.Range(1, 5)
.DoOnSubscribe(() => count++)
.Cache();// not yet subscribed to Range()
Assert.AreEqual(0, count);// relays events live
cached.Test().AssertResult(1, 2, 3, 4, 5);Assert.AreEqual(1, count);
// replays the buffered events
cached.Test().AssertResult(1, 2, 3, 4, 5);// no further subscriptions
Assert.AreEqual(1, count);
```*Since 0.0.4*
### Collect
Collects upstream items into a per-observer collection object created
via a function and added via a collector action and emits this collection
when the upstream completes.```cs
Observable.Range(1, 5)
.Collect(() => new List(), (a, b) => a.Add(b))
.Test()
.AssertResult(new List() { 1, 2, 3, 4, 5 });
```*Since: 0.0.3*
### CombineLatest
Combines the latest items of each source observable through
a mapper function, optionally delaying errors until all
of them terminates.```cs
ReactiveExtensions.CombineLatest(a => a, source1, source);new [] { source1, source2 }.CombineLatest(a => a, true);
```*Since: 0.0.5*
### Compose
Applies a function to the source at assembly-time and returns the
observable returned by this function.
This allows creating reusable set of operators to be applied on observables.```cs
Func, IObservable> applySchedulers =
o => o.SubscribeOn(Scheduler.NewThread).ObserveOn(Scheduler.UI);var o1 = Observable.Range(1, 5).Compose(applySchedulers);
var o2 = Observable.Range(10, 5).Compose(applySchedulers);
var o3 = Observable.Range(20, 5).Compose(applySchedulers);
```
*Since: 0.0.3*### ConcatEager
Concatenates a sequence of observables eagerly by running some
or all of them at once and emitting their items in order.
It is equivalent to `sources.ConcatMapEager(v => v)`.```cs
new[]
{
Observable.Range(1, 5),
Observable.Range(6, 5),
Observable.Range(11, 5)
}
.ToObservable()
.ConcatEager()
.Test()
.AssertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
```*Since: 0.0.3*
See also: [ConcatMapEager](#concatmapeager)### ConcatMap
Maps the upstream values into enumerables and emits their items in-order.
### ConcatMany
Concatenates (flattens) a sequence of observables.
### ConcatMapEager
Maps the upstream values into observables, runs some or all of them at once and emits items of
one such observable until it completes, then switches to the next observable, and so on until no
more observables are running.*Since: 0.0.2*
See also: [ConcatEager](#concateager)### Create
Creates an observable sequence by providing an emitter
API to bridge the callback world with the reactive world.```cs
ReactiveExtensions.Create(emitter => {Task.Factory.StartNew(() => {
for (int i = 0; i < 1000; i++) {
if (emitter.IsDisposed()) {
return;
}
emitter.OnNext(1);
}
if (emitter.IsDisposed()) {
return;
}
emitter.OnCompleted();
});}, true)
.Test()
.AwaitDone(TimeSpan.FromSeconds(5))
.AssertValueCount(1000)
.AssertNoError()
.AssertCompleted();
```*Since: 0.0.5*
### DoAfterNext
Call a handler after the current item has been emitted to the downstream.
### DoAfterTerminate
Call a handler after the upstream terminated normally or with an error.
### DoOnSubscribe
Call a handler just before the downstream subscribes to the upstream.
### DoOnDispose
Call a handler when the downstream disposes the sequence.
### DoFinally
Call a handler after the upstream terminates normally, with an error or the
downstream disposes the sequence.### IntervalRange
Emits a range of values over time.
```cs
ReactiveExtensions.IntervalRange(1, 5,
TimeSpan.FromSeconds(1), TimeSpan.FromSecoconds(2), NewThreadScheduler.Default)
.Test()
.AwaitDone(TimeSpan.FromSeconds(12))
.AssertResult(1, 2, 3, 4, 5);
```### MergeMany
Merges some or all inner observables provided via an observable sequence and emits their
items in a sequential manner.### ObserveOn
Observe the signals of the upstream on a specified scheduler and optionally
delay any error after all upstream items have been delivered.(The standard `ObserveOn` by default allows errors to cut ahead.)
### Repeat
Repeatedly re-subscribes to the source observable if the predicate
function returns true upon the completion of the previous
subscription.*Since: 0.0.3*
### Retry
Repeatedly re-subscribes to the source observable if the predicate
function returns true upon the failure of the previous
subscription.*Since: 0.0.3*
### SwitchIfEmpty
Switches to the (next) fallback observable if the main source
or a previous fallback is empty.```cs
var source = new Subject();var to = source.SwitchIfEmpty(Observable.Range(1, 5)).Test();
source.OnCompleted();
to.AssertResult(1, 2, 3, 4, 5);
```*Since: 0.0.3*
### SwitchMany
Switches to a new inner observable when the outer observable produces one,
disposing the previous active observable.
The operator can be configured to delay all errors until all sources have
terminated.*Since: 0.0.4*
See also: [SwitchMap](#switchmap)### SwitchMap
Switches to a new observable mapped via a function in response to
an new upstream item, disposing the previous active observable.
The operator can be configured to delay all errors until all sources have
terminated.*Since: 0.0.4*
See also: [SwitchMany](#switchmany)### Test
Subscribe a `TestObserver` to the observable sequence to perform various
convenient assertions.### ToSerialized
Wraps an `IObserver` or an `ISubject` and serializes the calls to its `OnNext`, `OnError` and `OnCompleted`
methods by making sure they are called non-overlappingly and non-concurrently.### UnsubscribeOn
Makes sure the `Dispose()` call towards the upstream happens on the specified
scheduler.*Since: 0.0.4*
### WithLatestFrom
Combines the latest values of multiple alternate observables with the value of the
main observable sequence through a function. Unlike `CombineLatest`, new items
from the alternate observables do not trigger an emission. The operator can
optionally delay errors from the alternate sources until the main source terminates.*Since: 0.0.4*
### Zip
Combines the next item of each source observable (a row of values) through
a mapper function, optionally delaying errors until no more
rows can be created.```cs
ReactiveExtensions.Zip(a => a, source1, source);new [] { Observable.Range(1, 5), Observable.Range(1, 10) }
.Zip(a => a[0] + a[1], true)
.Test()
.AssertResult(2, 4, 6, 8, 10);
```*Since: 0.0.5*
## Other classes
### TestObserver
An `IObserver` that offers a bunch of `AssertX` methods to check what signals
has been received from the upstream as well as have some trivial output checks
in a more convenient fashion.```cs
var to = new TestObserver();Observable.Range(1, 5).Subscribe(to);
to.AssertResult(1, 2, 3, 4, 5);
```There is the `Test()` extension method to make this more convenient in some cases:
```cs
Observable.Range(1, 5)
.Test()
.AwaitDone(TimeSpan.FromSeconds(5))
.AssertResult(1, 2, 3, 4 ,5)
```### TestScheduler
An `IScheduler` implementation that allows manually advancing a virtual
time and thus executing tasks up to a certain due time.```cs
var scheduler = new TestScheduler();var to = Observable.IntervalRange(1, 5, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), scheduler)
.Test();to.AssertEmpty();
scheduler.AdvanceTimeBy(TimeSpan.FromSeconds(1));
to.AssertValuesOnly(1);
scheduler.AdvanceTimeBy(TimeSpan.FromSeconds(4));
to.AssertValuesOnly(1, 2, 3);
scheduler.AdvanceTimeBy(TimeSpan.FromSeconds(4));
to.AssertResult(1, 2, 3, 4, 5);
Assert.False(scheduler.HasTasks());
```*Since 0.0.6*
### UnicastSubject
A special `ISubject` that supports exactly one `IObserver` during the subject's lifetime
and buffers signals until such observer subscribes to it.## ICompletableSource
A reactive type which signals an `OnCompleted()` or an `OnError()`, no items.
Consumer type: `ICompletableObserver`
Extension methods host: `CompletableSource`
*Since: 0.0.5*
### Factory methods
- `Amb`
- `AmbAll`
- `Concat`
- `ConcatAll`
- `Create`
- `Defer`
- `Empty`
- `Error`
- `FromAction`
- `FromTask`
- `Merge`
- `MergeAll`
- `Never`
- `Timer`
- `Using`### Instance methods
- `AndThen`
- `Compose`
- `Cache`
- `Delay`
- `DelaySubscription`
- `DoAfterTerminate`
- `DoFinally`
- `DoOnCompleted`
- `DoOnDispose`
- `DoOnError`
- `DoOnSubscribe`
- `DoOnTerminate`
- `ObserveOn`
- `OnErrorComplete`
- `OnErrorResumeNext`
- `OnTerminateDetach`
- `Repeat`
- `RepeatWhen`
- `Retry`
- `RetryWhen`
- `SubscribeOn`
- `TakeUntil`
- `Timeout`
- `UnsubscribeOn`### Consumer methods
- `BlockingSubscribe`
- `Subscribe`
- `SubscribeSafe`
- `SubscribeWith`
- `Test`
- `Wait`### Interoperation
- `AndThen` (with `IObservable`, `ISingleSource` & `IMaybeSource`)
- `ConcatMap` (on `Observable`)
- `FlatMap` (on `Observable`)
- `IgnoreAllElements` (on `IObservable`)
- `SwitchMap` (on `Observable`)
- `ToCompletable` (on `Task`)
- `ToMaybe`
- `ToObservable`
- `ToSingle`
- `ToTask`### CompletableSubject
A completable-based, hot subject that multicasts the termination event
it receives through its completable observer API surface.This subject supports an optional reference-counting behavior: when
all completable observers dispose before the subject terminates, it will
terminate its upstream connection (if any).*Since 0.0.6*
## ISingleSource
A reactive type wich signals an `OnSuccess()` or an `OnError()`.
Consumer type: `ISingleObserver`
Extension methods host: `SingleSource`
*Since: 0.0.5*
### Factory methods
- `Amb`
- `AmbAll`
- `Concat`
- `ConcatAll`
- `ConcatEager`
- `ConcatEagerAll`
- `Create`
- `Defer`
- `Error`
- `FromFunc`
- `FromTask`
- `Just`
- `Merge`
- `MergeAll`
- `Never`
- `Timer`
- `Using`
- `Zip`### Instance methods
- `Compose`
- `Filter`
- `FlatMap`
- `Cache`
- `Delay`
- `DelaySubscription`
- `DoAfterSuccess`
- `DoAfterTerminate`
- `DoOnDispose`
- `DoOnError`
- `DoOnSubscribe`
- `DoOnSuccess`
- `DoOnTerminate`
- `FlatMap` (onto `IEnumerable`, `ISingleSource`)
- `Map`
- `ObserveOn`
- `OnErrorResumeNext`
- `OnTerminateDetach`
- `Repeat`
- `RepeatWhen`
- `Retry`
- `RetryWhen`
- `SubscribeOn`
- `SubscribeSafe`
- `TakeUntil`
- `Timeout`
- `UnsubscribeOn`### Consumer methods
- `BlockingSubscribe`
- `Subscribe`
- `SubscribeSafe`
- `SubscribeWith`
- `Test`
- `Wait`### Interoperation
- `ConcatMap` (on `IObservable`)
- `ConcatMapEager` (on `IObservable`)
- `ElementAtOrDefault`
- `ElementAtOrError`
- `FirstOrDefault`
- `FirstOrError`
- `FlatMap` (onto `ICompletableSource`, `IMaybeSource`, `IObservable`)
- `IgnoreElement`
- `LastOrDefault`
- `LastOrError`
- `SingleOrDefault`
- `SingleOrError`
- `SwitchMap` (on `IObservable`)
- `ToMaybe`
- `ToObservable`
- `ToSingle`
- `ToTask`### SingleSubject
A single-based, hot subject that multicasts the value or failure event
it receives through its single observer API surface.This subject supports an optional reference-counting behavior: when
all single observers dispose before the subject succeeds or fails, it will
terminate its upstream connection (if any).*Since 0.0.9*
## IMaybeSource
A reactive type wich signals an `OnSuccess()`, an `OnError()` or an `OnCompleted()`
in a mutually exclusive fashion.Consumer type: `IMaybeObserver`
Extension methods host: `MaybeSource`
*Since: 0.0.5*
### Factory methods
- `Amb`
- `Create`
- `Concat`
- `ConcatAll`
- `ConcatEager`
- `ConcatEagerAll`
- `Defer`
- `Empty`
- `Error`
- `FromAction`
- `FromFunc`
- `FromTask`
- `Just`
- `Merge`
- `MergeAll`
- `Never`
- `Timer`
- `Using`
- `Zip`### Instance methods
- `Cache`
- `Compose`
- `DefaultIfEmpty`
- `Delay`
- `DelaySubscription`
- `DoAfterSuccess`
- `DoAfterTerminate`
- `DoFinally`
- `DoOnCompleted`
- `DoOnDispose`
- `DoOnError`
- `DoOnSubscribe`
- `DoOnSuccess`
- `DoOnTerminate`
- `Filter`
- `Map`
- `ObserveOn`
- `OnErrorComplete`
- `OnErrorResumeNext`
- `OnTerminateDetach`
- `Repeat`
- `RepeatWhen`
- `Retry`
- `RetryWhen`
- `SubscribeOn`
- `SwitchIfEmpty`
- `TakeUntil`
- `Timeout`
- `UnsubscribeOn`### Consumer methods
- `BlockingSubscribe`
- `Subscribe`
- `SubscribeSafe`
- `SubscribeWith`
- `Test`
- `Wait`### Interoperation
- `ConcatMap` (on `IObservable`)
- `ConcatMapEager` (on `IObservable`)
- `ElementAtIndex` (on `IObservable`)
- `FirstElement` (on `IObservable`)
- `FlatMap` (onto `ICompletableSource`, `ISingleSource`, `IObservable`, `IEnumerable`)
- `FlatMap` (on `IObservable`)
- `IgnoreElement`
- `LastElement` (on `IObservable`)
- `SingleElement` (on `IObservable`)
- `SwitchMap` (on `IObservable`)
- `ToObservable`
- `ToSingle`
- `ToTask`### MaybeSubject
A maybe-based, hot subject that multicasts the value or termination event
it receives through its maybe observer API surface.This subject supports an optional reference-counting behavior: when
all maybe observers dispose before the subject succeeds or terminates, it will
terminate its upstream connection (if any).*Since 0.0.9*
## IObservableSource
*Since 0.0.17*
A fully push-based observable source implementation that fixes the issues with
the `IObservable` interface.Consumer type: `ISignalObserver` (may change)
Main differences:
- `IObservable.Subscribe` is now void and thus fire-and-forget. Works both in synchronous and asynchronous cases because cancellation is now pushed down,
- `ISignalObserver.OnSubscribe` receives a Disposable upfront so it can be cancelled synchronously and asynchronously.### Factory methods
- `Amb`
- `CombineLatest`
- `Concat`
- `ConcatEager`
- `Create`
- `Defer`
- `Empty`
- `Error`
- `FromAction`
- `FromArray`
- `FromFunc`
- `Interval`
- `IntervalRange`
- `Just`
- `Merge`
- `Never`
- `Range`
- `RangeLong`
- `Switch`
- `Timer`
- `Using`
- `Zip`### Instance methods
- `All`
- `Any`
- `Buffer`
- `Cache`
- `Collect`
- `Compose`
- `ConcatMap`
- `ConcatMapEager`
- `Delay`
- `DelaySubscription`
- `DoAfterNext`
- `DoAfterTerminate`
- `DoFinally`
- `DoOnCompleted`
- `DoOnDispose`
- `DoOnError`
- `DoOnNext`
- `DoOnSubscribe`
- `DoOnTerminate`
- `ElementAt`
- `Filter`
- `First`
- `FlatMap`
- `GroupBy`
- `Hide`
- `IgnoreElements`
- `IsEmpty`
- `Join`
- `Last`
- `Map`
- `Max`
- `Min`
- `Multicast`
- `ObserveOn`
- `OnErrorResumeNext`
- `OnTerminateDetach`
- `Publish`
- `Reduce`
- `Repeat`
- `RepeatWhen`
- `Replay`
- `Retry`
- `RetryWhen`
- `Single`
- `Skip`
- `SkipLast`
- `SkipUntil`
- `SkipWhile`
- `SubscribeOn`
- `Sum`
- `SwitchIfEmpty`
- `SwitchMap`
- `Take`
- `TakeLast`
- `TakeUntil`
- `TakeWhile`
- `Timeout`
- `ToDictionary`
- `ToList`
- `ToLookup`
- `UnsubscribeOn`
- `Window`
- `WithLatestFrom`### Consumer methods
- `BlockingEnumerable`
- `BlockingSubscribe`
- `BlockingSubscribeWhile`
- `BlockingFirst`
- `BlockingLast`
- `BlockingSingle`
- `BlockingTryFirst`
- `BlockingTryLast`
- `BlockingTrySingle`
- `Subscribe`
- `SubscribeWith`
- `Test`### Interoperation with other async types
- `ElementAtTask`
- `FirstTask`
- `FromTask`
- `IgnoreElementsTask`
- `LastTask`
- `SingleTask`
- `ToObservableSource` (on `T[]`, `IObservable`, `IEnumerable`, `Task`)
- `ToObservable` (into `IObservable`)### IConnectableObservableSource
Represents an observable source that can be connected and disconnected from,
allowing signal observers to gather up before the flow starts.- `AutoConnect`
- `RefCount`### PublishSubject
Multicasts the same items to one or more currently subscribed observers (same as an Rx.NET `Subject`).
### MonocastSubject
Buffers items until a single observer subscribes and replays/relays all items to it.
### CacheSubject
Caches some or all items and relays/replays it to current or future observers.
## IAsyncEnumerable
Removed in 0.0.28