Programowanie Reaktywne - Kombinatorzy - When-And-Then.
Artykuł ten jest częścią serii artykułów na temat Programowania reaktywnego.
Zapraszam na GitHub-a.
Tematy
- Wstęp
- Zabawa z czasem - Timer
- Kto za tym stoi? - Scheduler
- Nie zapominaj - Subscribe
- Zabawa z czasem - Interval
- Zabawa z czasem - Buffer
- Zabawa z czasem - Delay
- Zabawa z czasem - Sample
- Zabawa z czasem - Throttle
- Zabawa z czasem - Timestamp/TimeInterval
- Tworzymy dane - Generators
- Tworzymy dane - Własna klasa publikująca
- Marudzimy - Skip
- Marudzimy - Take
- Łap To! - ConsoleKey
- Kombinatorzy - Concat
- Kombinatorzy - Repeat
- Kombinatorzy - Start With
- Kombinatorzy - Ambiguous
- Kombinatorzy - Merge
- Kombinatorzy - Zip
- Kombinatorzy - Switch
- Kombinatorzy - When-And-Then
- Kombinatorzy - Combine Latest
- Transformers - Select
- Transformers - OfType and Cast
- Transformers - Metadata
- Bileciki do kontroli - Unit Tests of Interval
- Bileciki do kontroli - Unit Tests of Observer Interval
- Bileciki do kontroli - Unit Tests of Create Cold/Hot Observable
- Szpryca - AutoFac
Wstęp
Nie tak dawno przedstawiałem zamek błyskawiczny (Zip). Istnieje jeszcze jedna możliwość pozwalająca na łączenie znacznie więcej w jedną całość. Tak by publikacja danych na połączony strumień odbywała się dopiero gdy dostaniemy wszystkie próbki z źródłowych strumieni.
Observable.When-And-Then
Do zbudowanie plecionki z dowolnej ilości strumieni (minimum jednego), wykorzystujemy operator Observable.When. Nie występuje on sam jest tutaj dodatkowo dwa dodatkowe pod operatory:
- And - służy do dołączania kolejnych strumieni poprzez dopisanie .Add(strumień),
- Then - ostatnia operacja łączy wyniki w klasę. Zbiera wszystkie porcje danych od strumieni i publikuje wynik.
Z tych elementów możemy tworzyć plecionkę…
Poniższy fragment to przygotowanie kilu dystrybutorów, do testu. Jest tutaj nowa metoda rozszerzająca BreakWhenKey opisana nieco niżej.
1
2
3
4
5
6
var observableStream1 = GeneratorFactory.CreateGenerator(0, 100, 1, 100);
var observableStream2 = GeneratorFactory.CreateGenerator(0, 100, 1, 60);
var observableStream3 = GeneratorFactory.CreateGenerator(0, 100, 1, 120);
var observableProvider = new ObservableProvider();
observableProvider.ConsoleKey.BreakWhenKey(ConsoleKey.Enter);
Po przygotowaniu strumieni bazowych należy je ze sobą spleść. Przykład poniżej przedstawia powiązanie strumieni różnego typu. Dwa dystrybutory pochodzą z ObservableProvider. Dzięki użyciu ConsoleKey mamy możliwość częściowego kontrolowania kiedy Then wykona dystrybucję nowych danych. Drugim warunkiem jest TimeCounter ale to tylko dlatego, że dostarcza danych co 1s.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var whenAndThenSequence = Observable.When(observableStream1
.And(observableStream2)
.And(observableStream3)
.And(observableProvider.ConsoleKey)
.And(observableProvider.TimeCounter)
.Then((first, second, third, consoleKey, time) =>
new {
One = first,
Two = second,
Three = third,
Key = consoleKey.Key,
Time = time
})
);
Wychodząc od pierwszego strumienia observableStream1 dodajemy kolejne (ile chcemy). Korzystając z operatora Add(strumyk) Ostatnim etapem jest użycie Then i tutaj należy pamiętać. Tyle ile strumieni dodamy tyle trzeba przygotować parametrów w lambdzie. A sama budowa obiektu już zależy od nas jak będzie wyglądał.
Ostatni fragment kodu, dotyczy nowej metody, która rozszerza strumyk ObservableConsoleKey. BreakWhenKey po prostu zapisuje się do dystrybutora i dodaje warunek zakończenia publikacji wciśniętych klawiszów gdy wciśniemy określony przez exitKey klawisz.
1
2
3
4
5
6
7
8
9
10
11
12
13
public static class HelpingExtensions
{
public static IDisposable BreakWhenKey(this ObservableConsoleKey source, System.ConsoleKey exitKey)
{
var subscription = source
.Subscribe(key =>
{
if (key.Key != exitKey)
{
return;
}
source.Stop();
Zakończenie
Plecionka jaką zbudujemy przy wykorzystaniu powyższych operatorów, może być przydatna gdy chcemy złączyć wiele strumieni i uzyskiwać jeden.
Może mieć też zastosowanie nieco inne, po splocie może się przydać gdy kolejny raz już przyjdzie się “powiesić” na wskutek walki ze środowiskami ;)….
Jest to post wchodzący w skład podjętego wyzwania ogłoszonego przez MIROBURN we vlogu z dnia 3 lutego 2018 roku.
Celem wyzwania jest systematyczne działanie w ciągu 30 dni.
Postanowiłem pisać post dziennie o tematyce Programowania Reaktywnego dla platformy .NET.
Wszelkie źródła związane z postami znajdują się na repozytorium GitHub.
Stan obecny wyzwania: 30 z 30 dni.
Referencje:
- MSDN - Getting Started with Rx,
- MSDN - Reactive Extensions,
- 101 Rx Samples,
- ReactiveX,
- Code Project,
- GitHub
Wcześniejszy: Programowanie Reaktywne - Kombinatorzy - Switch
Następny: Programowanie Reaktywne - Kombinatorzy - Combine Latest