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
Ludzie lubią ułatwiać sobie życie. Programiści to też podobno ludzie ;) dlatego pewnie postępują podobnie. Czasem z lenistwa, innym razem z własnych nieprzymuszonych chęci. Branża IT nieustannie się rozwija. Powstają takie wspaniałości jak wstrzykiwanie zależności;)
Warto było by i w rodzinie Rx-owatych dostawać to co się chce i kiedy się chce.
AutoFac
Hmm posłużę się tutaj moją ulubioną biblioteką do wstrzykiwania szprycy w konstruktorach. AutoFac. Nie ma róży bez kolców… By ktoś miał lepiej inny musi mieć gorzej. Dlatego wszystkie wstrzykiwane środki trzeba wcześniej przygotować. Kontener trzeba załadować przed podróżą. Przykładowo rejestrujemy obiekt Interval. Niestety w tej formie możemy dokonać jedynie jednorazowej rejestracji. Wynika to z faktu, że musimy zidentyfikować ten tworzony obiekt, i dzieje się to poprzez IObservable<long>.
1
2
3
4
5
6
7
8
9
10
11
var builder = new ContainerBuilder();
builder
.Register(c => Observable.Interval(TimeSpan.FromMilliseconds(100)))
.As<IObservable<long>>()
.SingleInstance();
builder.RegisterType<ObservableTimeCounter>().SingleInstance();
builder.RegisterType<Clock>();
builder.RegisterType<Part>();
Rejestrujemy także w ten sposób kilka innych obiektów, np. ObservableTimeCounter, Clock, Part.
Obiekty Rx-owe będą wstrzykiwane wielokrotnie, dlatego dobrze by je było zrobić jako Singleton-y.
Jak już sobie porejestrujemy obiekty. To można je powyciągać.
1
2
3
4
5
6
7
8
var container = InitContainer();
container.Resolve<Clock>();
for (var i = 0; i < 7; i++)
{
container.Resolve<Part>();
}
Dla przykładu użyjemy obiektu Clock do wyświetlania zegara. Oraz kilu obiektów Part. Ale dzięki singleton-kom możemy wielokrotnie się podpinać pod zarejestrowane czasowe wyzwalacze.
A jak poprosić o obiekt Rx-a. Tak jak każdy inny:p, wykorzystując uchwyt do zarejestrowanego w kontenerze obiektu.
1
2
3
4
5
6
7
8
9
public Clock(ObservableTimeCounter interval, Object obj)
{
_obj = obj;
interval.Subscribe(time =>
{
lock (_obj)
{
Console.SetCursorPosition(Console.WindowWidth - 8, 0);
Wstrzyknięty został obiekt ObservableTimeCounter, można już się zarejestrować.
Jest tutaj jeszcze jeden trik, jaki musiałem zastosować ze względu na pisanie na konsole. Obiekt, wstrzykiwany może być wykorzystywany w wielu miejsca. A służ on blokowaniu dostępu do określonego obszaru sekcji krytycznej.
W przeciwnym wypadku byłby niezły bajzel. Im więcej byśmy dodali obiektów, tym częściej działy by się cuda na ekranie konsoli. A to dlatego, że działania na konsoli: np.:
- Console.SetCursorPosition - ustawienie pozycji kursora,
- Console.WriteLine - wypisanie na konsole danych.
Łącznie nie są to działania atomowe. I poprzez korzystanie ze strumienia i wielu subskrypcjom sekwencja wykonania działań na konsoli, może być losowa. Dzięki zablokowaniu działania na konsoli. Sytuacja została w prosty sposób ogarnięta. Jednak nie jest to dobra praktyka i ma na celu jedynie prezentację działania Rx-ów i AutoFac-a.
1
2
3
4
5
6
7
8
public Part(IObservable<long> interval, Object obj)
{
_obj = obj;
_guid = Guid.NewGuid().ToString().Substring(0, 5);
_top = count;
count++;
interval.Subscribe(OnNext);
Zakończenie
Oczywiście istnieje inne wyjście z problemu rejestrowania wielu obiektów np. Interval. Ale o tym myślę przy następnej okazji.
Kod z Wami!
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 - Bileciki do kontroli - Unit Tests of Create Cold/Hot Observable