IObserver and IObservable in C# for Observer vs Delegates, Events

前端 未结 2 1240
[愿得一人]
[愿得一人] 2020-12-25 07:55

All I am trying to do is implementing the observer pattern.

So, I came up with this solution:

We have a PoliceHeadQuarters whose primary job is to send noti

相关标签:
2条回答
  • 2020-12-25 08:35

    Here's a modification of MSDN example to fit your framework:

        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();
            }
        }
    
    0 讨论(0)
  • 2020-12-25 08:55

    Another suggestion - you probably want to consider leveraging the reactive extensions library for any code using IObservable. The nuget package is Rx-Main and the homepage for it is here: http://msdn.microsoft.com/en-us/data/gg577609.aspx

    This will save you a lot of boilerplate code. Here's a super simple example:

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

    It will output:

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

    Reactive Extensions is a big subject, and a very powerful library - worth investigating. I recommend the hands-on lab from the link above.

    You would probably want to embed those subscriptions within your Inspector, SubInspector immplementatinos to more closely reflect your code. But hopefully this gives you an insight into what you can do with Rx.

    0 讨论(0)
提交回复
热议问题