GoDev

Blog programisty.

Programowanie Reaktywne - Kombinatorzy - When-And-Then.


Artykuł ten jest częścią serii artykułów na temat Programowania reaktywnego.

Zapraszam na GitHub-a.

Tematy

  1. Wstęp
  2. Zabawa z czasem - Timer
  3. Kto za tym stoi? - Scheduler
  4. Nie zapominaj - Subscribe
  5. Zabawa z czasem - Interval
  6. Zabawa z czasem - Buffer
  7. Zabawa z czasem - Delay
  8. Zabawa z czasem - Sample
  9. Zabawa z czasem - Throttle
  10. Zabawa z czasem - Timestamp/TimeInterval
  11. Tworzymy dane - Generators
  12. Tworzymy dane - Własna klasa publikująca
  13. Marudzimy - Skip
  14. Marudzimy - Take
  15. Łap To! - ConsoleKey
  16. Kombinatorzy - Concat
  17. Kombinatorzy - Repeat
  18. Kombinatorzy - Start With
  19. Kombinatorzy - Ambiguous
  20. Kombinatorzy - Merge
  21. Kombinatorzy - Zip
  22. Kombinatorzy - Switch
  23. Kombinatorzy - When-And-Then
  24. Kombinatorzy - Combine Latest
  25. Transformers - Select
  26. Transformers - OfType and Cast
  27. Transformers - Metadata
  28. Bileciki do kontroli - Unit Tests of Interval
  29. Bileciki do kontroli - Unit Tests of Observer Interval
  30. Bileciki do kontroli - Unit Tests of Create Cold/Hot Observable
  31. Szpryca - AutoFac

Wstęp

Reactive Extensions - When-And-Then 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
      })
);

Reactive Extensions - When-And-Then

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:


Wcześniejszy: Programowanie Reaktywne - Kombinatorzy - Switch

Następny: Programowanie Reaktywne - Kombinatorzy - Combine Latest