• IObserver<T>(IObservable<T>) vs ObservableCollection vs INotifyPropertyChanged


    下面是稍微修改过的MSDN的IObservable例子。

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

    下面是一个用ObservableCollection实现自动保存功能的Collection.

        /// <summary>
        /// Keep objects in the collection mirrored on a disk storage device, and support restore of collection from save disk file
        /// </summary>
        /// <typeparam name="T">Type of object in the collection</typeparam>
        public class AutoSaveCollection<T> : ObservableCollection<T>, IDisposable
        {
            private string fileName;
    
            private IFormatter formatter = new BinaryFormatter();
    
            /// <summary>
            /// Constructor
            /// </summary>
            /// <param name="fileName">Full filename to back the collection on disk</param>
            /// <param name="restoreFromFile">Restore collection from file</param>
            public AutoSaveCollection(string fileName, bool restoreFromFile)
                : base()
            {
                this.fileName = fileName;
                if (restoreFromFile)
                {
                    if (File.Exists(this.fileName))
                    {
                        Restore();
                    }
                }
                else
                {
                    if (File.Exists(this.fileName))
                    {
                        File.Delete(this.fileName);
                    }
                }
    
                base.CollectionChanged += observableCollection_CollectionChanged;
            }
    
            /// <summary>
            /// This event handler is triggered whenever the observable collection has been changed.  Trigger save to disk based on the change
            /// </summary>
            /// <param name="sender">self</param>
            /// <param name="e">change type</param>
            private void observableCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        if (e.NewItems != null)
                        {
                            SaveNew(e.NewItems.ToArray<T>());
                        }
                        break;
                    case NotifyCollectionChangedAction.Move:
                    case NotifyCollectionChangedAction.Remove:
                    case NotifyCollectionChangedAction.Replace:
                    case NotifyCollectionChangedAction.Reset:
                        SaveAll();
                        break;
                }
            }
    
            /// <summary>
            /// Discard the disk file.
            /// </summary>
            public void Discard()
            {
                base.Clear();
                if (File.Exists(this.fileName))
                {
                    File.Delete(this.fileName);
                }
            }
    
            /// <summary>
            /// Save everything stored in the collection to disk again (eg when collection item has been removed or when exiting)
            /// </summary>
            public void SaveAll()
            {
                string backupFileName = null;
                try
                {
                    backupFileName = Helpers.RenameIfExists(this.fileName);
                    using (FileStream stream = new FileStream(this.fileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
                    {
                        foreach (T item in this)
                        {
                            this.formatter.Serialize(stream, item);
                        }
                    }
    
                    try
                    {
                        if (File.Exists(backupFileName))
                        {
                            File.Delete(backupFileName);
                        }
                    }
                    catch (IOException ex)
                    {
                        Logger.LogException(ex, "I/O failure");
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, "Failed to save objects", this.fileName);
    
                    if (!string.IsNullOrEmpty(backupFileName) && File.Exists(backupFileName))
                    {
                        File.Move(backupFileName, fileName);
                    }
    
                    throw;
                }
            }
    
            /// <summary>
            /// Save new items directly to disk (don't bother add them to collection (to save memory))
            /// </summary>
            /// <param name="newItems"></param>
            public void SaveNew(params T[] newItems)
            {
                SaveNew((IEnumerable<T>)newItems);
            }
    
            private void SaveNew(IEnumerable<T> newItems)
            {
                try
                {
                    using (FileStream stream = new FileStream(this.fileName, FileMode.Append, FileAccess.Write, FileShare.Read))
                    {
                        foreach (T item in newItems)
                        {
                            this.formatter.Serialize(stream, item);
                        }
                    }
                    return;
                }
                catch (Exception ex)
                {
                    Logger.LogException(ex, "Exception adding data to file", this.fileName);
                }
    
                SaveAll();
            }
    
            /// <summary>
            /// Restore saved collection from disk file
            /// </summary>
            public void Restore()
            {
                Stream stream = null;
                try
                {
                    if (!File.Exists(this.fileName))
                    {
                        return;
                    }
    
                    base.Clear();
    
                    using (stream = new FileStream(this.fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        while (stream.Position < stream.Length)
                        {
                            T item = (T)this.formatter.Deserialize(stream);
                            if (item != null)
                            {
                                base.Add(item);
                            }
                        }
                    }
                }
                catch (IOException ex)
                {
                    Logger.LogException(ex, "Exception when restoring checkpoint", fileName);
                }
            }
    
            /// <summary>
            /// On dispose, save everything in the collection to disk at once.
            /// </summary>
            void IDisposable.Dispose()
            {
                base.CollectionChanged -= observableCollection_CollectionChanged;
                if (base.Count > 0)
                {
                    SaveAll();
                }
            }
        }

    INotifyPropertyChanged只是一个接口,主要用于当类的属性值发生改变的时候通知,貌似在WPF用的比较多。

    public class UserNPC:INotifyPropertyChanged
    {
        private string name;
        public string Name { 
            get { return name; } 
            set { name = value; onPropertyChanged(this, "Name"); } 
        }
        public int grade;
        public int Grade { 
            get { return grade; } 
            set { grade = value; onPropertyChanged(this, "Grade"); } 
        }
    
        // Declare the PropertyChanged event
        public event PropertyChangedEventHandler PropertyChanged;
    
        // OnPropertyChanged will raise the PropertyChanged event passing the
        // source property that is being updated.
        private void onPropertyChanged(object sender, string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(sender, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    IObserver<T>&IObservable<T>是对设计模式的实现跟总结,ObservableCollection跟INotifyPropertyChanged通过事件来通知。

  • 相关阅读:
    C#生成PDF总结
    Oracle删除当前用户下所有的表的方法
    C#操作oracle 到ExecuteNonQuery卡死不执行
    C#中事件的使用
    初探three.js光源
    d3.js 地铁轨道交通项目实战
    初探three.js
    d3.js 绘制北京市地铁线路状况图(部分)
    d3.js 共享交换平台demo
    d3.js 实现烟花鲜果
  • 原文地址:https://www.cnblogs.com/bwangff/p/4325743.html
Copyright © 2020-2023  润新知