IObserver et IObservable en C# pour les observateurs vs délégués, événements

Tout ce que j'essaie de faire, c'est mettre en place le schéma de l'observateur.

donc, j'ai trouvé cette solution:

nous avons un quartier général de la police dont la tâche principale est d'envoyer des notifications à tous ceux qui y sont abonnés. Considérez que les classes DSP, Inspector et SubInspector sont souscrites aux quartiers généraux de la police.

utilisant des événements et des délégués j'ai écrit

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()));
    }
}

et voici comment je invoqué it

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

ainsi, les classes D'inspecteur et de sous-inspecteur reçoivent notification chaque fois que la fonction RaiseANotification() est invoquée.

il semble que le cadre DotNet 4, 4.5 supporte une nouvelle voie appelée IObserver et IObservable.

est-ce que quelqu'un peut me donner un exemple super simple en utilisant IObservable et IObserver pattern pour le scénario ci-dessus? J'ai googlé pour trouver seulement les exemples disponibles dans l'internet lourd et difficile à comprendre.

Ma touche: (probablement, je pense que c'est faux)

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

Merci d'avance.

modifier: Quelqu'un a également dit que la documentation MSDN est également incorrecte pour IObservable @ IObservable vs Plaine des Événements ou Pourquoi Devrais-je utiliser IObservable? .

11
demandé sur Community 2013-06-10 12:46:53

2 réponses

voici une modification de L'exemple MSDN pour s'adapter à votre cadre:

    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();
        }
    }
26
répondu Spook 2013-06-10 09:08:35

une autre suggestion - vous voulez probablement envisager de tirer parti de la bibliothèque des extensions réactives pour tout code utilisant IObservable . Le paquet nuget est Rx-Main et la page d'accueil est ici: http://msdn.microsoft.com/en-us/data/gg577609.aspx

vous économiserez beaucoup de code boilerplate. Voici un exemple très simple:

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!");

il sortira:

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

réactif Extensions est un grand sujet, et une bibliothèque très puissante - intéressant d'étudier. Je recommande le laboratoire pratique à partir du lien ci-dessus.

vous voudriez probablement intégrer ces souscriptions dans votre inspecteur, sous-inspecteur implementatinos pour refléter plus étroitement votre code. Mais espérons que cela vous donne un aperçu de ce que vous pouvez faire avec Rx.

15
répondu James World 2013-06-10 10:44:05