2013-06-10 9 views
11

私がしようとしているのは、オブザーバパターンを実装することだけです。ObserverとDelegates、EventsのC#でのIObserverとIObservable

だから、私はこの解決策を考え出した:

私たちは、その主な仕事、それに加入しているすべての人に通知を送信することですPoliceHeadQuartersを持っています。 DSP、Inspector、SubInspectorクラスが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()が呼び出されるたびに、インスペクターとSubInspector両方のクラスは、通知を得ます。

DotNet Framework 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 ? 

感謝。

EDIT:MSDNのドキュメントも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

Microsoftの例は基本的なイベントアグリゲータを使用しているようです。より複雑ですが、最終的にはより柔軟なアプローチです。アグリゲータは、一連のIObserverを順番に呼び出す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

.Net GCが循環参照を処理するか、このコードが地獄のように漏れる可能性があります。 – Pharap

15

別の提案 - あなたはおそらくIObservableを使用して、任意のコードのための反応性の拡張ライブラリを活用することを検討したいです。ナゲットパッケージはRx-Mainで、そのホームページは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! 

反応性の拡張が大きな課題であり、非常に強力なライブラリ - 調べてみる価値。私は上のリンクからハンズオンラボをお勧めします。

Inspector、SubInspector immplementatinosにこれらのサブスクリプションを埋め込んで、コードをより正確に反映させたいと思うかもしれません。しかし、うまくいけば、これはあなたがRxでできることについての洞察を与えます。

+0

Rxに感謝します。それは徹底的に行く.. –