2009-07-31 14 views

उत्तर

33

आप IObservable को किसी ईवेंट के रूप में उपयोग कर सकते हैं, जो कोड IObservable प्रकार के गुणों के साथ ईवेंट को उजागर करता है, लेकिन यह वास्तव में बिंदु नहीं है।

वहाँ दो महत्वपूर्ण बातें IObservable के बारे में समझने के लिए कर रहे हैं: अतुल्यकालिक संचालन (जो आमतौर पर एक एकल मान) और घटनाओं:

  1. यह दो अवधारणाओं है कि हम से पहले एकजुट करने के लिए कैसे नहीं पता था कि एकीकृत (जो आमतौर पर हमेशा के लिए जाते हैं)।

  2. यह composable है। सीएलआर घटनाओं के विपरीत, IAsyncResult, या INotifyCollectionChanged यह हमें सामान्य घटनाओं और एसिंक्रोनस संचालन से विशिष्ट घटनाओं को बनाने की अनुमति देता है।

यहां एक उदाहरण है कि मैं इस दोपहर में काम पर भाग गया।

सिल्वरलाइट में कुछ प्रभाव हैं जो आप छवि नियंत्रण पर लागू कर सकते हैं जिसे सामान्य नियंत्रण पर लागू नहीं किया जा सकता है। जब नियंत्रण की सामग्री बदल जाती है तो इन सीमाओं को प्राप्त करने के लिए मैं अपनी दृश्य उपस्थिति को अपडेट करने की प्रतीक्षा कर सकता हूं और इसका स्क्रीनशॉट ले सकता हूं। फिर मैं अपने दृश्य प्रतिनिधित्व को छिपाना चाहता हूं, इसे स्नैपशॉट के साथ बदलना चाहता हूं, और छवि पर दृश्य प्रभाव लागू करना चाहता हूं। अब मैं छवि प्रभाव को नियंत्रण में लागू कर सकता हूं (माना जाता है कि यह इंटरैक्टिव नहीं है)।

यह प्रोग्राम छोटा होगा लेकिन इस तथ्य के लिए कि यह असीमित होना चाहिए। मैं पूरा करने के लिए लगातार दो अतुल्यकालिक कार्यों के लिए इंतज़ार करना होगा इससे पहले कि मैं छवि के लिए प्रभाव लागू कर सकते हैं:

  1. नियंत्रण की सामग्री बदल गया है
  2. नियंत्रण के दृश्य उपस्थिति अद्यतन किया जाता है

यहाँ मैं कैसे था आरएक्स का उपयोग करके इस समस्या को हल करें:

// A content control is a control that displays content. That content can be 
// anything at all like a string or another control. Every content control contains 
// another control: a ContentPresenter. The ContentPresenter's job is to generate 
// a visual representation of the Content property. For example, if the Content property 
// of the ContentControl is a string, the ContentPresenter creates a TextBlock and inserts 
// the string into it. On the other hand if the Content property is another control the 
// ContentPresenter just inserts it into the visual tree directly. 
public class MyContentControl : ContentControl 
{ 
    // A subject implements both IObservable and IObserver. When IObserver methods 
    // are called, it forwards those calls to all of its listeners. 
    // As a result it has roughly the same semantics as an event that we can "raise." 
    private Subject<object> contentChanged = new Subject<object>(); 

    // This is a reference to the ContentPresenter in the ContentControl's template 
    private ContentPresenter contentPresenter; 

    // This is a reference to the Image control within ContentControl's template. It is displayed on top of the ContentPresenter and has a cool blur effect applied to it. 
    private Image contentImageControl; 

    public MyContentControl() 
    { 
     // Using Rx we can create specific events from general events. 
     // In this case I want to create a specific event ("contentImageChanged") which 
     // gives me exactly the data I need to respond and update the UI. 
     var contentImageChanged = 
     // get the content from the content changed event 
     from content in contentChanged 
     where content != null 
     // Wait for the ContentPresenter's visual representation to update. 
     // ContentPresenter is data bound to the Content property, so it will 
     // update momentarily. 
     from _ in contentPresenter.GetLayoutUpdated().Take(1) 
     select new WritableBitmap(contentPresenter, new TranslateTransform()); 

     contentImageChanged.Subscribe(
     contentImage => 
     { 
      // Hide the content presenter now that we've taken a screen shot    
      contentPresenter.Visibility = Visibility.Collapsed; 

      // Set the image source of the image control to the snapshot 
      contentImageControl.ImageSource = contentImage; 
     }); 
    } 

    // This method is invoked when the Content property is changed. 
    protected override OnContentChanged(object oldContent, object newContent) 
    { 
     // show the content presenter before taking screenshot 
     contentPresenter.Visibility = Visibility.Visible; 

     // raise the content changed "event" 
     contentChanged.OnNext(newContent); 

     base.OnContentChanged(oldContent, newContent); 
    } 
} 

यह उदाहरण विशेष रूप से सरल है कि अनुक्रम के लिए केवल दो लगातार संचालन हैं। यहां तक ​​कि इस सरल उदाहरण में भी हम देख सकते हैं कि आरएक्स मूल्य जोड़ता है। इसके बिना मुझे यह सुनिश्चित करने के लिए राज्य चर का उपयोग करना पड़ता था कि घटनाएं एक निश्चित क्रम में फायरिंग कर रही हों। मुझे लेआउट अपडेटेड इवेंट से अलग होने के लिए कुछ सुंदर बदसूरत कोड भी लिखना होगा।

जब आप आरएक्स के साथ प्रोग्रामिंग कर रहे हैं तो यह सोचना है कि "मैं किस फ्रेम को प्रदान करता हूं?" और फिर इसे बनाओ। हमें घटनाओं के बारे में सोचने के लिए प्रशिक्षित किया जाता है जैसे कि सरल, इनपुट-संचालित चीजें ("माउसओवर", "माउसक्लिक", "कीप", आदि)। हालांकि, आपके ऐप के लिए बहुत जटिल और विशिष्ट नहीं हो सकता है ("GoogleMsdnMashupStockDataArrived", "DragStarting", और "ImageContentChanged")। जब आप अपने कार्यक्रमों को इस तरह से ढंकते हैं (बिल्कुल उस घटना को बनाएं जिसे मुझे की आवश्यकता है और फिर राज्य बदलकर इसका जवाब दें) आप पाएंगे कि उनके पास कम राज्य कीड़े हैं, अधिक आदेश दिए गए हैं, और पूरी तरह से अधिक आत्म-वर्णन कर रहे हैं।

समझे? :-)

+0

ग्रीटिंग उदाहरण (इसलिए +1) हालांकि मुझे लगता है कि मैं राज्य मशीन को देखना चाहूंगा, क्योंकि सभी प्रोग्रामर आरएक्स को समझने से पहले यह काफी समय लगेगा। मैं यह तय नहीं कर सकता कि पोस्ट प्रोग्रामर के पास कॉम्प साइंस डिग्री नहीं है, अगर आरएक्स बहुत दूर है ... –

3

यह घटना आधारित प्रोग्रामिंग मॉडल का सिर्फ एक विस्तार है। आप ऐसा कुछ बनाते हैं जो IObserver लागू करता है, और मूल रूप से आप कह रहे हैं "संग्रह में कुछ बदलते समय मैं क्या करना चाहता हूं"। इस तरह, यह सिर्फ एक मानकीकरण है कि हम सभी घटनाओं के साथ क्या कर रहे हैं।

वे इसे धक्का दे रहे हैं जैसे यह आईनेमेरेबल पैटर्न की तुलना में एक बड़ा चेहरा है। आईन्यूमेरेबल "पुल" है, जबकि IObservable "पुश" है।

सीधी घटनाओं पर एकमात्र लाभ जो मैं देखता हूं वह यह है कि यह एक मानक इंटरफ़ेस है। मैं यहां पर्यवेक्षण चयन के साथ एक बड़ा ओवरलैप देखता हूं (और INotifyCollectionChanged)। हो सकता है कि वे .NET के साथ PERL आदर्श वाक्य को अपनाने का प्रयास कर रहे हैं: "ऐसा करने के एक से अधिक तरीके हैं"।

+4

स्कॉट सवाल तो है, क्या ढांचे की तरह अगर IObservable और IObserver ढांचे के संस्करण 1 में लागू किया गया लगेगा पूरा करें। त्रुटि प्रबंधन और ईवेंट प्रोग्रामिंग composable किया गया होगा। एसिंक्रोनस और सिंक घटनाओं को संभालने का एक आम तरीका। समानांतर एक्सटेंशन IObservable प्रकारों का उपयोग किया होगा। लेकिन मुख्य बात यह है कि यह सभी शुरुआत से संगत हो सकता है, जो बहुत सारी चीजों को बहुत सरल बना देता है जो अब असंभव नहीं हैं। (यूनिट परीक्षण एसिंक्रोनस यूआई एक है जो मेरे सिर के ऊपर से दिमाग में आता है) – DouglasH

+1

@ डौलस, लेकिन हम इतिहास को फिर से लिख नहीं सकते हैं, इसलिए क्विज़न "ओल्डवे या आरएक्स" नहीं है, बल्कि "ओल्डवे या (ओल्डवे और आरएक्स") " –

+0

IObservable का मुख्य लाभ इसकी composability है। चूंकि आपके पास इसे ऑपरेटरों का निर्माण करने का एक बड़ा संग्रह है, जो IObservable इंटरफ़ेस पर भरोसा करते हैं, इसलिए आप बहुत जटिल तरीके से बहुत जटिल इंटरैक्शन बना सकते हैं। कच्चे कार्यक्रमों के साथ आपको सभी घटनाओं के आमंत्रणों का ट्रैक रखने के लिए बहुत सारी स्थिति का सहारा लेना होगा। – ionoy

3

मैं फायदे के बारे में सुनिश्चित नहीं हूँ, लेकिन मैं क्लासिक नेट की घटनाओं के साथ निम्नलिखित अंतर देखें:

त्रुटि सूचनाएं

क्लासिक घटनाओं इस के लिए एक अलग घटना की आवश्यकता होगी, या एक EventArgsError संपत्ति के साथ कक्षा को चेक करने की आवश्यकता है।

अंत अधिसूचना अधिसूचना

क्लासिक घटनाओं एक अलग या एक Final संपत्ति है कि जांच की ज़रूरत है के साथ इस के लिए घटना एक EventArgs वर्ग की आवश्यकता होगी।

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