MR. Dev

Blog programisty.

Programowanie Reaktywne - Łap To! - ConsoleKey.


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 - ConsoleKey Dzisiejszy post jest szczególny, gdyż to 15 post składający się na wyzwanie jakie podjąłem. Półmetek jest. Wiele pracy już zostało włożone, jeszcze więcej przede mną. Dziękuję wszystkim czytelnikom, i mam nadzieję, że udało mi się komuś pomóc.

Zostałem też sprowadzony do porządku. Nadmiernie obkładałem FB grupę, swoimi publikacjami. Wszystkie osoby jakie uraziłem tym działaniem przepraszam. I znacznie ograniczę wrzucanie swoich wypocin na publiczne grupy w mediach społecznościowych.

ConsoleKey

Dzisiaj zmienimy trochę podejście, i zaczniemy przechwytywać zdarzenia pochodzące od użytkownika. W tym celu stworzyłem klasę ObservableConsoleKey. Można zapisywać się na jej wewnętrzną listę. Tym samym po uruchomieniu nasłuchu na zdarzenia pochodzące wciskanych przycisków w konsoli. Będziemy mogli reagować.

1
2
3
4
public class ObservableConsoleKey : IObservable<ConsoleKeyInfo>, IDisposable
{
  private bool _catchKeys;
  private List<IObserver<ConsoleKeyInfo>> _observers;

Reactive Extensions - ConsoleKey

Publikacja wciśniętych klawiszy na stłumień odbywa się w metodzie Start. Dodatkowo użyłem zmiennej logicznej do kontroli pętli odbierającej dane z klawiatury i dystrybuującej do zapisanych zainteresowanych obiektów.

Przy pomocy publicznej metody Stop możemy przerwać pętlę i tym samym pozwolić na zakończanie programu w konsoli.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void Start()
{
  _catchKeys = true;

  while (_catchKeys)
  {
    var currentKey = Console.ReadKey(true);
    Publish(currentKey);
  }
}

public void Stop()
{
  _catchKeys = false;

Metoda jest bardzo prosta i w zasadzie zmienia zmienną logiczną _catchKeys na false.

Publikowanie wciśniętych klawiszy na strumień jest bardzo proste. Także użyte tutaj zostało LINQ i metoda ForEach. Jako parametr w wyzwalanej metodzie OnNext oczywiście przekazujemy przechwycony klawisz z konsoli.

1
2
3
4
private void Publish(ConsoleKeyInfo currentKey)
{
  _observers.ForEach(observer => observer.OnNext(currentKey));
}

Pozostałe elementy w klasie ObservableKeyConsole, są bardzo podobne do tych użytych w poprzednich klasach generatorów: ObservableValentinesDay, ObservableTimeCounter.

Ostatni fragment kodu dotyczy sposobu użycia nowego publishera. Jest bardzo podobnie do poprzednich z tą różnicą, że do dyspozycji mamy dwie wyżej opisane metody Start i Stop. Dzięki nim możemy sterować zachowaniem obiektu obserwowanego.

Zapis na strumień wykonujemy standardowo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
static void Main()
{
  var observableProvider = new ObservableProvider();

  observableProvider.ConsoleKey
    .Subscribe(consoleKey =>
    {
      Console.WriteLine(consoleKey.Key);

      if (consoleKey.Key == ConsoleKey.Enter)
      {
        observableProvider.ConsoleKey.Stop();
      }
    });

  observableProvider.ConsoleKey.Start();

Wykonujemy tutaj także ekstra sprawdzenie czy wciśnięty klawisz to Enter i gdy tak właśnie jest to wówczas zatrzymujemy pętlę przechwytującą klawiaturę konsoli. I tym samym możemy zatrzymać działanie programu w sposób naturalny.

Zakończenie

Tooooooo bardzoooooo krótki post. Wybrałem temat dość prosty do implementacji. Nie zawsze trzeba klepać multum lini kodu. Czasem trzeba coś prostego stworzyć. I myślę, że jest to bardzo ciekawe rozwiązanie.

Często czuję tutaj potrzebę użycia kontenera (AutoFac). I być może pojawią się posty o takiej tematyce. Wówczas mielibyśmy już dostęp w dowolnym miejscu programu do obiektów obserwowanych. W przypadku ObservableConsoleKey dało by to możliwość korzystania z wprowadzanych na konsolę danych w dowolnym miejscu aplikacji. Ciekawa koncepcja…


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 - Marudzimy - Take

Następny: Programowanie Reaktywne - Kombinatorzy - Concat