2013-06-10 4 views
11

मैं जो करने की कोशिश कर रहा हूं वह पर्यवेक्षक पैटर्न को कार्यान्वित कर रहा है।ऑब्सर्वर बनाम प्रतिनिधियों के लिए सी # में IObserver और IObservable, घटनाक्रम

तो, मैं इस समाधान के साथ आया था:

हम एक PoliceHeadQuarters जिसका प्राथमिक काम उन सभी जो यह की सदस्यता ली है पर सूचनाएं भेजने की है। इस बात पर विचार करें कि डीएसपी, इंस्पेक्टर और सब इंस्पेक्टर कक्षाएं पुलिस हेडक्वॉर्टर की सदस्यता लेती हैं।

का उपयोग करते हुए घटनाक्रम और प्रतिनिधियों मैं

public class HeadQuarters 
{ 
    public delegate void NewDelegate(object sender, EventArgs e); 
    public event EventHandler NewEvent; 
    public void RaiseANotification() 
    { 
     var handler = this.NewEvent; 
     if (handler != null) 
     { 
      handler(this, new EventArgs()); 
     } 
    } 
} 

public class SubInspector 
{ 
    public void Listen(object sender, EventArgs e) 
    { 
     MessageBox.Show(string.Format("Event Notification received by sender = {0} with eventArguments = {1}", sender, e.ToString())); 
    } 
} 

public class Inspector 
{ 
    public void Listen(object sender, EventArgs e) 
    { 
     MessageBox.Show(string.Format("Event Notification received by sender = {0} with eventArguments = {1}", sender, e.ToString())); 
    } 
} 

लिखा था और यह मैं इसे कैसे

 var headQuarters = new HeadQuarters(); 
     var SubInspector = new SubInspector(); 
     var Inspector = new Inspector(); 
     headQuarters.NewEvent += Inspector.Listen; 
     headQuarters.NewEvent += SubInspector.Listen; 
     headQuarters.RaiseANotification(); 

तो लागू है, दोनों इंस्पेक्टर और सब इंस्पेक्टर कक्षाएं सूचना मिलती है तो जब भी समारोह RaiseANotification() शुरू हो जाती है।

ऐसा लगता है कि डॉटनेट फ्रेमवर्क 4, 4.5 IObserver और IObservable नामक एक नए तरीके का समर्थन करता है।

क्या कोई मुझे उपरोक्त परिदृश्य के लिए IObservable और IObserver पैटर्न का उपयोग करके एक सुपर सरल उदाहरण दे सकता है? मैं केवल इंटरनेट में उपलब्ध उदाहरणों को ढूंढने के लिए गुमराह हूं और समझने में मुश्किल हूं।

मेरे hinch: (शायद मुझे लगता है कि यह गलत है)

class DSP : IObserver //since it observes the headquarters ? 
    class PoliceHeadQuarters: IObservable // since here's where we send the notifications ? 

अग्रिम धन्यवाद।

संपादित करें: किसी ने यह भी कहा कि एमएसडीएन दस्तावेज IObservable @ IObservable vs Plain Events or Why Should I use IObservable? के लिए भी गलत है।

+0

http://msdn.microsoft.com/en-us/library/dd990377.aspx - एक अच्छा उदाहरण है, आप इसे संकलित करने और चलाने का प्रयास क्यों नहीं करते? – Spook

+0

@Spook: समस्या वास्तव में मैं उन उदाहरणों के साथ अपने परिदृश्य को सह-संबंधित नहीं कर सकता। किसी भी कंकाल कोड संरचना को आगे जाने में मेरी मदद करनी चाहिए .. –

+0

ऐसा लगता है कि माइक्रोसॉफ्ट का उदाहरण मूल इवेंट एग्रीगेटर का उपयोग कर रहा है। एक और जटिल लेकिन अंत में, अधिक लचीला दृष्टिकोण। एग्रीगेटर IObserver के प्रकारों को अनुक्रम में बुलाता है।मुझे लगता है कि इसीलिए इंटरफेस-आधारित दृष्टिकोण प्रतिनिधियों के विरोध में उपयोग किया जाता है। –

उत्तर

25

यहाँ MSDN उदाहरण के संशोधन अपने ढांचे फिट करने के लिए है:

public struct Message 
    { 
     string text; 

     public Message(string newText) 
     { 
      this.text = newText; 
     } 

     public string Text 
     { 
      get 
      { 
       return this.text; 
      } 
     } 
    } 

    public class Headquarters : IObservable<Message> 
    { 
     public Headquarters() 
     { 
      observers = new List<IObserver<Message>>(); 
     } 

     private List<IObserver<Message>> observers; 

     public IDisposable Subscribe(IObserver<Message> observer) 
     { 
      if (!observers.Contains(observer)) 
       observers.Add(observer); 
      return new Unsubscriber(observers, observer); 
     } 

     private class Unsubscriber : IDisposable 
     { 
      private List<IObserver<Message>> _observers; 
      private IObserver<Message> _observer; 

      public Unsubscriber(List<IObserver<Message>> observers, IObserver<Message> observer) 
      { 
       this._observers = observers; 
       this._observer = observer; 
      } 

      public void Dispose() 
      { 
       if (_observer != null && _observers.Contains(_observer)) 
        _observers.Remove(_observer); 
      } 
     } 

     public void SendMessage(Nullable<Message> loc) 
     { 
      foreach (var observer in observers) 
      { 
       if (!loc.HasValue) 
        observer.OnError(new MessageUnknownException()); 
       else 
        observer.OnNext(loc.Value); 
      } 
     } 

     public void EndTransmission() 
     { 
      foreach (var observer in observers.ToArray()) 
       if (observers.Contains(observer)) 
        observer.OnCompleted(); 

      observers.Clear(); 
     } 
    } 

    public class MessageUnknownException : Exception 
    { 
     internal MessageUnknownException() 
     { 
     } 
    } 

    public class Inspector : IObserver<Message> 
    { 
     private IDisposable unsubscriber; 
     private string instName; 

     public Inspector(string name) 
     { 
      this.instName = name; 
     } 

     public string Name 
     { 
      get 
      { 
       return this.instName; 
      } 
     } 

     public virtual void Subscribe(IObservable<Message> provider) 
     { 
      if (provider != null) 
       unsubscriber = provider.Subscribe(this); 
     } 

     public virtual void OnCompleted() 
     { 
      Console.WriteLine("The headquarters has completed transmitting data to {0}.", this.Name); 
      this.Unsubscribe(); 
     } 

     public virtual void OnError(Exception e) 
     { 
      Console.WriteLine("{0}: Cannot get message from headquarters.", this.Name); 
     } 

     public virtual void OnNext(Message value) 
     { 
      Console.WriteLine("{1}: Message I got from headquarters: {0}", value.Text, this.Name); 
     } 

     public virtual void Unsubscribe() 
     { 
      unsubscriber.Dispose(); 
     } 
    } 

    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      Inspector inspector1 = new Inspector("Greg Lestrade"); 
      Inspector inspector2 = new Inspector("Sherlock Holmes"); 

      Headquarters headquarters = new Headquarters(); 

      inspector1.Subscribe(headquarters); 
      inspector2.Subscribe(headquarters); 

      headquarters.SendMessage(new Message("Catch Moriarty!")); 
      headquarters.EndTransmission(); 

      Console.ReadKey(); 
     } 
    } 
+1

क्या इंस्पेक्टर ने प्रोफेसर को पकड़ लिया है या नहीं, अब मुझे पैटर्न पकड़ने में सक्षम होना चाहिए। बहुत धन्यवाद। –

+2

खुशी है कि मैं मदद कर सकता हूं। सौभाग्य! – Spook

+0

अच्छी बात यह है कि नेट जीसी सर्कुलर संदर्भों को संभाल सकता है या यह कोड नरक के रूप में रिसाव होगा। – Pharap

15

एक और सुझाव - आप शायद IObservable उपयोग कर किसी भी कोड के लिए प्रतिक्रियाशील एक्सटेंशन पुस्तकालय का लाभ पर विचार करना चाहते। Nuget पैकेज आरएक्स-मेन है और इसके लिए होमपेज यहां है: http://msdn.microsoft.com/en-us/data/gg577609.aspx

यह आपको बहुत सारे बॉयलरप्लेट कोड को बचाएगा। यहाँ एक सुपर सरल उदाहरण है:

var hq = new Subject<string>(); 

var inspectorSubscription = hq.Subscribe(
    m => Console.WriteLine("Inspector received: " + m)); 

var subInspectorSubscription = hq.Subscribe(
    m => Console.WriteLine("Sub Inspector received: " + m)); 

hq.OnNext("Catch Moriarty!"); 

उत्पादन यह होगा:

Inspector received: Catch Moriarty! 
Sub Inspector received: Catch Moriarty! 

रिएक्टिव एक्सटेंशन एक बड़ा विषय है और एक बहुत शक्तिशाली पुस्तकालय - की जांच के लायक। मैं ऊपर दिए गए लिंक से हैंड-ऑन लैब की सलाह देता हूं।

आप शायद अपने इंस्पेक्टर, सबइंस्पेक्टर अपरिपक्वेटिनोस के भीतर उन सब्सक्रिप्शन को अपने कोड को अधिक बारीकी से प्रतिबिंबित करना चाहते हैं। लेकिन उम्मीद है कि यह आपको आरएक्स के साथ क्या कर सकता है में अंतर्दृष्टि प्रदान करता है।

+0

आरएक्स के लिए धन्यवाद नहीं दे सकता। पूरी तरह से जाना होगा .. –

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