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
To już ostatni post z rodziny timer-owatych. Omówione zostaną dwa proste operatory. Ale co ważniejsze, zaimplementujemy kolejne dwa własne. Rx oparty jest o rozszerzone metody, dlatego bardzo łatwo jest dodać kolejne potrzebne “stworki”.
TimeInterval, Timestamp
Pierwszy fragment kodu dotyczy oznaczania danych na strumieniu interwałem czasowym. Dzięki takiemu działaniu, można zaobserwować ile czasu upłynęło pomiędzy poszczególnymi danymi publikowanymi do obserwatorów. Po takiej konwersji otrzymujemy nie jedną, a dwa pola:
- Value - to wartość podawana przez strumień bazowy,
- Interval - okres jaki upłynął od ostatniego przetwarzania strumienia.
Przykład oczywiście na GitHub-ie w projekcie o nazwie StampAndInterval, a fragment poniżej.
1
2
3
4
5
6
7
8
9
10
11
12
13
var observableInterval = Observable.Interval(TimeSpan.FromSeconds(1));
_subscribeTimeInterval = observableInterval
.TimeInterval()
.Subscribe(
x => Console.WriteLine("TimeInterval \t\t{0} \t{1}", x.Value, x.Interval)
);
_subscribeTimestamp = observableInterval
.Timestamp()
.Subscribe(
x => Console.WriteLine("Timestamp \t\t{0} \t{1}", x.Value, x.Timestamp)
);
Już wcześniej w postach korzystaliśmy z operatora opakowującego strumienie tak by uzyskać oprócz danych np. stempel czasowy. Do tego celu posłużyliśmy się operatorem: .Timestamp(). Po opakowaniu otrzymujemy dwie właściwości:
- Value - to wartość podawana przez strumień bazowy,
- Timestamp - czas danych publikowanych na strumień.
Extension Methods
Zajmiemy się teraz odwróceniem działania Timestamp(), TimeInterval(). W tym celu należy nieco się napocić, i zaimplementować własne rozszerzenia do interfejsu IObservable.
1
2
3
4
5
6
7
8
9
10
11
12
public static class RXExtensions
{
public static IObservable<TSource> RemoveTimeInterval<TSource>(this IObservable<TimeInterval<TSource>> source)
{
return source.Select(x => x.Value);
}
public static IObservable<TSource> RemoveTimestamp<TSource>(this IObservable<Timestamped<TSource>> source)
{
return source.Select(x => x.Value);
}
}
Po implementacji metod, należy nie marnować kodu i go użyć. Strumień w tym przypadku musi już posiadać odpowiednie opakowanie. W pierwszym przykładzie: RemoveTimestamp, należy opakować oczywiście Timestamp-em. I tak właśnie się dzieje w pierwszym przykładzie poniżej.
1
2
3
4
5
6
7
var observableInterval = Observable.Interval(TimeSpan.FromSeconds(1)).Timestamp();
_subscribeWithoutTimestamp = observableInterval
.RemoveTimestamp()
.Subscribe(
x => Console.WriteLine("Remove Timestamp \t{0}", x)
);
Analogicznie postąpimy z drugim przykładem, z tą różnicą że będziemy korzystać z operatorów dotyczących TimeInterval. Odpowiednio .TimeInterval() i .RemoveTimeInterval().
1
2
3
4
5
6
7
var observableInterval = Observable.Interval(TimeSpan.FromSeconds(1)).TimeInterval();
_subscribeWithoutTimeInterval = observableInterval
.RemoveTimeInterval()
.Subscribe(
x => Console.WriteLine("Remove TimeInterval \t{0}", x)
);
Zakończenie
Kończąc tą partie postów dotyczących czasu. Mam nadzieję, iż przysłużyłem się komuś moją malutką wiedzą na ten temat. W kolejnych poznawać będziemy inne mechanizmy, operatory jakie dostarczają biblioteki Reactive Extensions. Zapraszam do śledzenia. I dziękuję za obecność.
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 - Zabawa z czasem - Throttle
Następny: Programowanie Reaktywne - Tworzymy dane - Generators