設定檔變更即時監控類(觀察者模式)

來源:互聯網
上載者:User

因為經常要寫各種設定檔,所以曾經寫過監控檔案變更的方法,後來其他地方要用到時每次都要copy不方便,於是修改了下代碼,封裝成一個類庫,這樣只要需要監控的檔案都可以通過這個類庫來實現監控,以下是代碼

Observer.cs,檔案監控類,利用微軟的FileSystemWatcher 實現即時監控,只監控修改

/// <summary>    /// 檔案觀察者,只監控檔案內容修改,不監控其他諸如檔案名稱被改,檔案被刪等    /// </summary>    public sealed class Observer    {        /// <summary>        /// 要通知的對象集合        /// </summary>        private List<Watcher> _watchers;        /// <summary>        /// 檔案夾監視者        /// </summary>        private FileSystemWatcher _fsw;        /// <summary>        /// 當前監控的檔案夾完整路徑        /// </summary>        public string FullPath        {            get            {                return this._fsw.Path;            }        }        /// <summary>        /// 檔案觀察者,只監控檔案內容修改,不監控其他諸如檔案名稱被改,檔案被刪等        /// </summary>        public Observer()            : this(false)        {        }        public Observer(bool includeSubdirectories)            : this(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "Config", "*Config.xml", includeSubdirectories)        {        }        public Observer(string folderPhyPath, string fileFiler)            : this(folderPhyPath, fileFiler, false)        {         }        /// <summary>        /// 檔案觀察者,只監控檔案內容修改,不監控其他諸如檔案名稱被改,檔案被刪等        /// </summary>        /// <param name="folderPhyPath">要監控的檔案夾實體路徑,預設為當前該程式的根目錄下的Config檔案夾</param>        /// <param name="fileFiler">擷取或設定篩選字串,用於確定在目錄中監視哪些檔案,預設*Config.xml</param>        /// <param name="includeSubdirectories">是否監控子檔案夾,預設false</param>        public Observer(string folderPhyPath, string fileFiler, bool includeSubdirectories)        {            this._watchers = new List<Watcher>();            _fsw = new FileSystemWatcher();            _fsw.Path = folderPhyPath.ToStandardPath();            _fsw.NotifyFilter = NotifyFilters.LastWrite;            _fsw.Filter = fileFiler;            _fsw.Changed += new FileSystemEventHandler(fsw_Changed);            _fsw.EnableRaisingEvents = true;            _fsw.IncludeSubdirectories = includeSubdirectories;        }        /// <summary>        /// 當檔案夾內監控內容發生變化時        /// </summary>        /// <param name="sender"></param>        /// <param name="e"></param>        private void fsw_Changed(object sender, FileSystemEventArgs e)        {            Thread.Sleep(3000);            IEnumerable<Watcher> watchers = this._watchers.Where(wt => wt.RightPath(e.FullPath));            if (watchers != null && watchers.Count() > 0)            {                foreach (Watcher watcher in watchers)                {                    watcher.Notify();                }            }        }        /// <summary>        /// 判斷檔案是否屬於當前監控的檔案夾        /// </summary>        /// <param name="fullFilePath">要判斷的檔案完整路徑</param>        /// <returns></returns>        internal bool FilesIn(string fullFilePath)        {            FileInfo fi = new FileInfo(fullFilePath);            bool isIn = false;            string watchPath = new DirectoryInfo(_fsw.Path).FullName;            DirectoryInfo di = fi.Directory;            do            {                if (di != null)                {                    isIn = di.FullName == watchPath;                    if (!isIn)                    {                        di = di.Parent;                    }                }                else                {                    break;                }                if (!this._fsw.IncludeSubdirectories)                {                    break;                }            }            while (!isIn);            return isIn;        }        /// <summary>        /// 添加被通知者        /// </summary>        /// <param name="afw"></param>        public void Attach(Watcher wt)        {            if (!this._watchers.Contains(wt))            {                this._watchers.Add(wt);            }        }        /// <summary>        /// 移除被通知者        /// </summary>        /// <param name="afw"></param>        public void Detch(Watcher wt)        {            this._watchers.Remove(wt);        }    }


 

Watcher.cs,通過事件實現配置變更時同步通知,因為FileSystemWatcher的Changed 事件觸發時會激發兩次,所以利用lastWriteTime來阻止重複變更通知事件,順便練習了下自訂異常和自訂EventArgs

public delegate void ChangedEventHandler(object sender, FileChangedEventArgs e);    public class Watcher    {        public event ChangedEventHandler Changed;        /// <summary>        /// 觀察者        /// </summary>        private Observer _observer;        /// <summary>        /// 檔案實體路徑        /// </summary>        private readonly string _fullPath;        /// <summary>        /// Watcher記錄到的檔案最後修改時間        /// </summary>        private DateTime _lastWriteTime;        public Observer Observer        {            get            {                return this._observer;            }        }        public Watcher(string fullPath, Observer observer)        {            this._fullPath = fullPath.ToStandardPath();            this._lastWriteTime = File.GetLastWriteTime(this._fullPath);            if (!observer.FilesIn(this._fullPath))            {                throw new FileNotInDirectoryException("指定檔案並不存在於指定檔案夾內", this._fullPath, observer.FullPath);            }            this._observer = observer;            this.Attach();        }        public void Attach()        {            this._observer.Attach(this);        }        public void Detch()        {            this._observer.Detch(this);        }        internal void Notify()        {            DateTime filesLastWriteTime = File.GetLastWriteTime(this._fullPath);            if (this._lastWriteTime != filesLastWriteTime)            {                this._lastWriteTime = filesLastWriteTime;                this.OnChange(new FileChangedEventArgs(this._fullPath));            }        }        protected virtual void OnChange(FileChangedEventArgs e)        {            if (Changed != null)            {                Changed(this, e);            }        }        internal bool RightPath(string fullPath)        {            return this._fullPath == fullPath;        }    }    /// <summary>    /// 包含變化檔案相關的資料    /// </summary>    [Serializable]    [System.Runtime.InteropServices.ComVisible(true)]    public class FileChangedEventArgs : EventArgs    {        private readonly string _fullPath;        public FileChangedEventArgs(string fullPath)        {            this._fullPath = fullPath.ToStandardPath();        }        public string FullPath        {            get            {                return this._fullPath;            }        }    }    /// <summary>    /// 當指定檔案不存在於指定檔案夾內時引發異常    /// </summary>    [Serializable]    [System.Runtime.InteropServices.ComVisible(true)]    public class FileNotInDirectoryException : IOException    {        private readonly string _fileName, _directoryName;        public FileNotInDirectoryException()            : base("File Not In Directory")        {        }        public FileNotInDirectoryException(string message)            : base(message)        {        }        public FileNotInDirectoryException(string message, Exception innerException)            : base(message, innerException)        {        }        //        // 摘要:        //     使用指定錯誤資訊和對作為此異常原因的內部異常的引用來初始化 System.IO.FileNotFoundException 類的新執行個體。        //        // 參數:        //   message:        //     解釋異常原因的錯誤資訊。        //        //   fileName:        //     一個 System.String,它包含要驗證的檔案的完整路徑        //        //   directoryName        //     一個 System.String,它包含要驗證的檔案夾的完整路徑        //        //   innerException:        //     導致當前異常的異常。如果 innerException 參數不為 null,則當前異常在處理內部異常的 catch 塊中引發。        public FileNotInDirectoryException(string message, string fileName, string directoryName)            : base(message)        {            this._fileName = fileName;            this._directoryName = directoryName;        }        //        // 摘要:        //     用指定的序列化和上下文資訊初始化 System.IO.IOException 類的新執行個體。        //        // 參數:        //   info:        //     用於序列化或還原序列化對象的資料。        //        //   context:        //     對象的源和目標。        protected FileNotInDirectoryException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)            : base(info, context)        {        }        public FileNotInDirectoryException(string message, string fileName, string directoryName, Exception innerException)            : base(message, innerException)        {            this._fileName = fileName;            this._directoryName = directoryName;        }        public string FileName        {            get            {                return this._fileName;            }        }        public string DirectoryName        {            get            {                return this._directoryName;            }        }        public override string ToString()        {            return "File:" + this._fileName + Environment.NewLine +                "Directory:" + this._directoryName + Environment.NewLine +                base.ToString();        }    }    internal static class FullPathHelper    {        public static string ToStandardPath(this string fullPath)        {            return fullPath.Replace('/', '\\');        }    }

使用代碼

public class Demo    {        private Watcher _watcher;        private Observer _observer;                public Demo()        {            this._observer = new Observer();            string fullPath = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "Config\\SSOConfig.xml";            this._watcher = new Watcher(fullPath, this._observer);            this._watcher.Changed += new ChangedEventHandler(_watcher_Changed);            this.InitParameters(fullPath);        }        private void _watcher_Changed(object sender, FileChangedEventArgs e)        {            this.InitParameters(e.FullPath);        }        private void InitParameters(string fullPath)        {        }}

 

有些代碼還是寫的不好,有點重複的感覺,沒有定義介面或抽象,因為我只針對檔案變更監控,沒有預見可能會變更的地方,如果要實現監控其他的變更的話,可以修改相應的監控代碼,只要是FileSystemWatcher能監控的

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.