Reactive Extensions–Observable.FromAsyncPattern

W wcześniejszych wersjach .NET Framework metody asynchroniczne implementujące wzorzec Begin\End były bardzo powszechne w użyciu. RX posiada metody pomocnicze, umożliwiające konwersję asynchronicznego źródła danych do IObservable.

Rozważmy to na przykładzie. Załóżmy, że mamy web service, zawierający jakieś metody. Można oczywiście dla takiego serwisu wygenerować asynchroniczne metody. Jeśli chcecie popraktykować możecie skorzystać z tej, darmowej usługi:

http://services.aonaware.com/DictService/DictService.asmx

Oczywiście dodając w Visual Studio referencję do usługi należy zaznaczyć pole Generate Asynchronous operations:

image

 

Zostaną m.in. wygenerowane metody BeginMatchInDict oraz EndMatchInDict. Powyższa usługa pozwala na wyszukiwanie słów w słowniku. MatchInDict posiada kilka parametrów przyjmujących np. słowo kluczowe, typ wyszukiwania czy typ słownika. Chcąc z nich skorzystać bez użycia RX należy zdefiniować własny callback:

private void TextBoxTextChanged(object sender, TextChangedEventArgs e)
{  
    DictServiceSoapClient client = new DictServiceSoapClient("DictServiceSoap"); 
    client.BeginMatchInDict("wn", termTextBox.Text, "prefix", SearchCallback, client);  
}
private void SearchCallback(IAsyncResult result)
{
    var client = (DictServiceSoapClient) result.AsyncState;
    DictionaryWord[] words = client.EndMatchInDict(result);            
    UpdateResults(words);
}

Za pomocą RX można ten sam efekt uzyskać korzystając z Observable.FromAsyncPattern:

DictServiceSoapClient client = new DictServiceSoapClient("DictServiceSoap");

var dictionarySource =
Observable.FromAsyncPattern<string, string, string, DictionaryWord[]>(client.BeginMatchInDict,
                                                             client.EndMatchInDict);




var inputSource =
Observable.FromEventPattern<TextChangedEventArgs>(termTextBox, "TextChanged").Select(i =>
                                                                            ((TextBox) i.Sender)
                                                                                .Text);

inputSource.SelectMany(input => dictionarySource("wn", input, "prefix")).
ObserveOn(SynchronizationContext.Current).Subscribe(UpdateResults);

Na początku tworzymy dwa źródła danych. Jedno dla metod asynchronicznych drugie dla zdarzenia TextChanged obiektu TextBox, w którym użytkownik może wpisać szukaną frazę. Następnie za pomocą LINQ, przechodzimy przez każdy element inputSource (czyli przez każde wpisane słowo) i i wywołujemy dictionarySource. Wynikiem będzie oczywiście lista zawierająca szukane słowa. W następnym poście rozwinę trochę powyższy przykład aby pokazać, że posiadanie IObservable ułatwia znacząco przetwarzanie danych.

Leave a Reply

Your email address will not be published.