2010-05-14 30 views
10

का उपयोग कर एक आरईएसटी क्लाइंट एपीआई बनाना मैं प्रतिक्रियाशील एक्सटेंशन (आरएक्स) के लिए सही उपयोग के मामलों के आसपास अपना सिर प्राप्त करने की कोशिश कर रहा हूं। उदाहरण आने वाले उदाहरण यूआई इवेंट (ड्रैग और ड्रॉप, ड्राइंग) हैं, और सुझाव हैं कि आरएक्स एसिंक्रोनस एप्लिकेशन/ऑपरेशंस जैसे वेब सेवा कॉल के लिए उपयुक्त है।प्रतिक्रियाशील एक्सटेंशन (आरएक्स)

मैं एक ऐसे एप्लिकेशन पर काम कर रहा हूं जहां मुझे एक आरईएसटी सेवा के लिए एक छोटा क्लाइंट एपीआई लिखना है। मुझे कुछ संदर्भ डेटा (हवाई अड्डे, एयरलाइंस और स्थिति) प्राप्त करने के लिए चार आरईएसटी एंड-पॉइंट्स, तीन कॉल करने की आवश्यकता है, और चौथा मुख्य सेवा है जो आपको किसी दिए गए हवाई अड्डे के लिए उड़ान का समय देगी।

मैं तीन संदर्भ डाटा सेवाओं को उजागर वर्गों बनाया है, और तरीकों कुछ इस तरह दिखाई:

public Observable<IEnumerable<Airport>> GetAirports() 
public Observable<IEnumerable<Airline>> GetAirlines() 
public Observable<IEnumerable<Status>> GetStatuses() 
public Observable<IEnumerable<Flights>> GetFlights(string airport) 

मैं प्रत्येक उड़ान के लिए एक संदर्भ हवाई अड्डे से प्रस्थान यह है रखना चाहते हैं, और मेरे GetFlights विधि में एयरलाइन उड़ान का संचालन कर रही है। ऐसा करने के लिए मुझे GetAirports और GetA Box से उपलब्ध होने की आवश्यकता है। प्रत्येक हवाई अड्डे, एयरलाइन और स्थिति को डिक्शनरी (यानी शब्दकोश) में जोड़ा जाएगा ताकि प्रत्येक उड़ान को पार करते समय मैं आसानी से संदर्भ सेट कर सकूं।

flight.Airport = _airports[flightNode.Attribute("airport").Value] 
flight.Airline = _airlines[flightNode.Attribute("airline").Value] 
flight.Status = _statuses[flightNode.Attribute("status").Value] 

मेरे वर्तमान कार्यान्वयन अब इस तरह दिखता है:

public IObservable<IEnumerable<Flight>> GetFlightsFrom(Airport fromAirport) 
{ 
    var airports = new AirportNamesService().GetAirports(); 
    var airlines = new AirlineNamesService().GetAirlines(); 
    var statuses = new StatusService().GetStautses(); 


    var referenceData = airports 
     .ForkJoin(airlines, (allAirports, allAirlines) => 
          { 
           Airports.AddRange(allAirports); 
           Airlines.AddRange(allAirlines); 
           return new Unit(); 
          }) 
     .ForkJoin(statuses, (nothing, allStatuses) => 
          { 
           Statuses.AddRange(allStatuses); 
           return new Unit(); 
          }); 

    string url = string.Format(_serviceUrl, 1, 7, fromAirport.Code); 

    var flights = from data in referenceData 
        from flight in GetFlightsFrom(url) 
        select flight; 

    return flights; 
} 

private IObservable<IEnumerable<Flight>> GetFlightsFrom(string url) 
{ 
    return WebRequestFactory.GetData(new Uri(url), ParseFlightsXml); 
} 

वर्तमान कार्यान्वयन सेर्गेई के जवाब पर आधारित है, और अनुक्रमिक निष्पादन सुनिश्चित करने के लिए ForkJoin का उपयोग करता है और मैं संदर्भ डेटा उड़ानों से पहले लोड हो जाता है कि। यह कार्यान्वयन मेरे पिछले कार्यान्वयन की तरह "संदर्भ डेटा लोडेड" ईवेंट को आग लगाने से अधिक सुरुचिपूर्ण है।

+0

उत्तर अपडेट किया गया - भी, इस धागे पर एक नज़र डालें: http://social.msdn.microsoft.com/Forums/en/rx/thread/20e9fea1-304f-4926-aa02-49ed558a84f5 - दिखाता है कि कैसे अपना लिखना है कस्टम बफरिंग –

उत्तर

2

मुझे लगता है कि, यदि आप प्रत्येक आरईएसटी कॉल से इकाइयों की एक सूची प्राप्त कर रहे हैं, तो आपके कॉल के पास थोड़ा अलग हस्ताक्षर होना चाहिए - आप रिटर्न संग्रह में प्रत्येक मान को नहीं देख रहे हैं, आप कॉल पूर्ण होने की घटना को देख रहे हैं।

public IObservable<Aiports> GetAirports() 

अगले कदम के समानांतर में पहले तीन चलाने के लिए और उन सभी को पर प्रतीक्षा करने के लिए होगा:: तो हवाई अड्डों के लिए, यह हस्ताक्षर होना चाहिए

var ports_lines_statuses = 
    Observable.ForkJoin(GetAirports(), GetAirlines(), GetStatuses()); 

तीसरे चरण की रचना करने के लिए किया woul GetFlights() के साथ abservable ऊपर:

var decoratedFlights = 
    from pls in ports_lines_statuses 
    let airport = MyAirportFunc(pls) 
    from flight in GetFlights(airport) 
    select flight; 

संपादित करें: मैं अभी भी समझ में नहीं आता क्यों अपनी सेवाओं

वापसी 10
IObservable<Airport> 

IObservable<IEnumerable<Airport>> 

AFAIK के बजाय

, बाकी से कॉल आप एक बार में सभी संस्थाओं मिलता है - लेकिन हो सकता है आप पेजिंग करते हैं?

var allAirports = new AirportNamesService() 
     .GetAirports().BufferWithCount(int.MaxValue); 
... 

तो फिर तुम आवेदन कर सकते हैं ForkJoin:

var ports_lines_statuses = 
    allAirports 
     .ForkJoin(allAirlines, PortsLinesSelector) 
     .ForkJoin(statuses, ... 

ports_lines_statuses समय पर एक ही ईवेंट शामिल है जो शामिल होगा वैसे भी, आप RX चाहते हैं बफरिंग आप .BufferWithCount() इस्तेमाल कर सकते हैं कर सभी संदर्भ डेटा।

संपादित करें: यहाँ एक और एक है, हाल में ढाला ListObservable का उपयोग कर (नवीनतम रिलीज केवल):

allAiports = airports.Start(); 
allAirlines = airlines.Start(); 
allStatuses = statuses.Start(); 

... 
whenReferenceDataLoaded = 
    Observable.Join(airports.WhenCompleted() 
       .And(airlines.WhenCompleted()) 
       .And(statuses.WhenCompleted()) 
       Then((p, l, s) => new Unit())); 



    public static IObservable<Unit> WhenCompleted<T>(this IObservable<T> source) 
    { 
     return source 
      .Materialize() 
      .Where(n => n.Kind == NotificationKind.OnCompleted) 
      .Select(_ => new Unit()); 
    } 
+0

मैं वास्तव में सभी एयरलाइंस, हवाईअड्डे और परिस्थितियों को पहले "एक बैच" में प्राप्त करना चाहता हूं, क्योंकि जब मुझे उड़ानें मिलती हैं तो मुझे उन तीन संदर्भ डेटा सेट मौजूद होने की आवश्यकता होती है ताकि मैं उन्हें एक उड़ान से जोड़ सकूं। इसलिए मुझे इस डिक्शनर्ट <स्ट्रिंग, एयरपोर्ट> जैसे निर्देशों में हवाई अड्डे प्राप्त करने की आवश्यकता है, ताकि मैं कर सकूं: flight.Airport = हवाई अड्डे [flightXml.AirportCode]। –

+0

मैंने नए विधि हस्ताक्षर के साथ प्रश्न अद्यतन किया। आप कहां सही हैं, मैं वास्तव में सभी हवाई अड्डे, एयरलाइंस और स्थिति एक बार में प्राप्त करना चाहता हूं। क्या मैं PortLinesSelector में सही हूं हवाईअड्डे और एयरलाइनों को जोड़ने का एक तरीका है, और फिर मुझे परिणाम के साथ पिछले परिणाम को गठबंधन करने के लिए दूसरी विधि की आवश्यकता है? मैंने सिल्वरलाइट 3/4 के लिए आरएक्स की नवीनतम रिलीज को डाउनलोड करने का प्रयास किया, लेकिन वे अवलोकन (केवल शुरुआत) पर विधि प्रारंभ() नहीं ढूंढ सका। –

+0

@ जोनास-फूसेसो हां, पोर्ट्सलाइनस चयनकर्ता कुछ (बंदरगाहों, रेखाएं) => नए {बंदरगाहों, रेखाएं}, और दूसरा चयनकर्ता इस पर तीसरा परिणाम संलग्न करेगा। यहां विचार यह है कि जितना संभव हो सके कार्यात्मक शैली को रखने की कोशिश करें और केवल स्थानीय चर का उपयोग करने के बजाय पाइपलाइन के माध्यम से डेटा पास करें। अवलोकन पर प्रारंभ() केवल .Net4 रिलीज पर है, इसलिए आपको इसे तब तक इंतजार करना होगा जब तक कि यह दूसरों को पोर्ट न किया जाए ... –

0

उपयोग के मामले यहाँ है लगाकर - IEnumerable ठीक है। यदि आप कहना चाहते हैं, तो सूचित करें कि एक नई उड़ान कहां आती है, फिर Observable.Generate के भीतर एक पुल आधारित आरईएसटी कॉल लपेटना कुछ मूल्य का हो सकता है।

+0

तो आरएक्स मेरे परिदृश्य में एक आरईएसटी ग्राहक बनाने के लिए एक अच्छा दृष्टिकोण नहीं है? चूंकि यह WP7 है, मैं इसे तुल्यकालिक नहीं बना सकता, इसलिए विकल्प होगा: GetA OxAsync, और एक GetA Online पूर्ण घटना है। मुझे फिर GetA OxAsync, GetAirportsAsync और GetStatusesAsync को कॉल करना होगा, और GetFlights को कॉल करने से पहले सभी तीन कॉलबैक ईवेंटों को आग लगाना होगा ..? मैं रीफ्रेश करने के लिए हर 3 मिनट में GetFlights सेवा को फिर से कॉल करने के लिए अपनी विधि का विस्तार करने की भी योजना बना रहा था। इसलिए नई उड़ान वस्तुओं को देखते हुए आने के रूप में एक अच्छा विचार लगता है ..? –

+0

यदि अंतर्निहित एपीआई केवल एसिंक आधारित है, तो आरएक्स बहुत अधिक समझ में आता है। Observable.Generate ... –

संबंधित मुद्दे