1. 程式人生 > >委託與事件-委託事件案例(三)

委託與事件-委託事件案例(三)

前言

  這兩天一直在想如何結合實際案例來結束委託與事件的講解,下面講解兩個事例,用來加深對委託及事件的理解。

事例一(分頁功能)

  本場景是用來講解使用的,具體內容功能需自行填補實現。用委託加事件來實現分頁功能的通用。按上一節講解中的邏輯處理,分為訂閱者和釋出者,一樣的可以先定義訂閱者感興趣的物件,然後釋出者,訂閱者。再就是主程式呼叫。

   

     /// <summary>
    /// 首先定義訂閱者感興趣的物件,本例感興趣的是上一頁下一頁等方法。這裡使用Action抽象
    /// </summary>
    public class PageChangeEventArgs : EventArgs
    {
        public string Action { get; set; }
        public int PageIndex { get; set; }
        public PageChangeEventArgs() { }
        public PageChangeEventArgs(string action, int pageIndex)
        {
            this.Action = action;
            this.PageIndex = pageIndex;
        }
    }

    /// <summary>
    /// 定義釋出者
    /// </summary>
    public class PageActionPubliser
    {
        //定義委託
        public delegate void PageActionEventHandler(object sender, PageChangeEventArgs e);
        //定義委託型別的事件
        public event PageActionEventHandler PageAction;
        //定義保護方法判斷委託事件是否為空,傳入引數e型別為EventArgs
        protected void OnPageAction(PageChangeEventArgs e)
        {
            if (PageAction != null)
            {
                PageAction(this, e);
            }
            //PageAction?.Invoke(this, e);也可這樣寫
        }

        //編寫觸發事件、上一頁
        public void PreviousClick( PageChangeEventArgs e)

        {
            OnPageAction(new PageChangeEventArgs("Previous",e.PageIndex));
        }
        //下一頁
        public void NextClick( PageChangeEventArgs e)
        {
            OnPageAction(new PageChangeEventArgs("Next",e.PageIndex));
        }
 
    }

 
    /// <summary>
    /// 定義訂閱者
    /// </summary>
    public class Recevice
    {
        /// <summary>
        /// 具體分頁內容的實現,訂閱者
        /// </summary>
        public static void BindPage(object sender, PageChangeEventArgs e)
        {

            //假設最大頁數為10
            int MaxIndex = 10;

            if (e.PageIndex == 0 && e.Action == "Previous")
            {
                //當前0頁,不能上一頁
            }

            if (e.PageIndex == MaxIndex - 1 && e.Action == "Next")
            {
                //已是最後一頁,不能下一頁
            }
            switch (e.Action)
            {
                case "Previous":
                    e.PageIndex--;
                    break;
 
                default:
                    e.PageIndex++;
                    break;
            }
            Console.WriteLine($"已跳轉到第{e.PageIndex}頁");
        }
        
    }

         /// <summary>
        /// 這裡使用的是控制檯應用程式進行模擬
        /// </summary>
        /// <param name="args"></param>
    class Program
    {
       
        static void Main(string[] args)
        {
            //繫結註冊事件
            PageActionPubliser pageActionPubliser = new PageActionPubliser();
            pageActionPubliser.PageAction += Recevice.BindPage;
            Console.WriteLine("請選擇上一頁或者下一頁:上一頁(A)/下一頁(B)");
            string answer=Console.ReadLine();
            PageChangeEventArgs pageChangeEventArgs = new PageChangeEventArgs();

            //假設當前頁為5
            pageChangeEventArgs.PageIndex = 5;
            if (answer=="A")
            {                        
            pageActionPubliser.PreviousClick(pageChangeEventArgs);
            }

            else
            {
                pageActionPubliser.NextClick(pageChangeEventArgs);
            }

        }

    }    

  

  在這裡委託加事件的分頁功能實現完成了。其實原理很簡單的,當點選上一頁或者下一頁的時候,這時候因為因為已經繫結註冊了這個事件。 它就會具體執行其中的操作。還是要具體去實踐編寫操作除錯一下,就很快知道它的執行順序、也能很快的掌握的。

 

事例二(新車到達提醒)

  這個案例,簡要的表述就是在車庫中新到達了車輛時會對管理者傳送通知。首先我們也先分析下。訂閱者是管理者。訂閱者感興趣的物件是啥呢?感興趣的物件是有沒有新車達到。

  然後,我們開始這個的一個設計。

    

    /// <summary>
    /// 定義訂閱者感興趣的物件
    /// </summary>
    public class NewCarsEventArgs : EventArgs
    {
        public string NewCardName { get; set; }
        public NewCarsEventArgs() { }
        public NewCarsEventArgs(string newCardName)
        {
            this.NewCardName = newCardName;
        }
    }


    /// <summary>
    /// 定義釋出者
    /// </summary>
    public class NewCarsPublisher
    {
        public delegate void CarsEventHandler(object sender ,NewCarsEventArgs e);
        public event CarsEventHandler Cars;
        private void OnCars(NewCarsEventArgs e)
        {
            if (Cars!=null)
            {
                Cars(this,e);
            }
        }
        public void NewCarsArrivals(NewCarsEventArgs e)
        {
            OnCars(e);
        }
    }


    public class NewCarsRecevie
    {
        public static void Manager(object sender,NewCarsEventArgs e)
        {
            Console.WriteLine($"通知:新車{e.NewCardName}到了!");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            NewCarsPublisher newCarsPublisher = new NewCarsPublisher();
            newCarsPublisher.Cars += NewCarsRecevie.Manager;
            Console.WriteLine("請輸入到達車輛的名稱:");
            string name=Console.ReadLine();
            Console.WriteLine("到達車輛是否是新車(Y/N):");
            string answer = Console.ReadLine();
            if (answer=="Y")
            {
                NewCarsEventArgs newCarsEventArgs = new NewCarsEventArgs() { NewCardName=name};

               newCarsPublisher.NewCarsArrivals(newCarsEventArgs);
            }
            else
            {
                Console.WriteLine("不是新車不對訂閱者傳送通知!");
            }
        }
}   

 

  謹記,事件基於委託,為委託提供了一種釋出/訂閱機制。理解發布訂閱機制就會容易多了。一旦理清楚,發現好像也並不是很難的。多多消化一下,自己動手去想一下例項。去寫一下。很快能掌握的。

總結

  委託與事件到這裡就大結局了。一些列的問題也解決了。心中的疑惑也揭開了。下面我們就接著基礎系列寫其他的了。

  

  曾經,我們懵懵懂懂地看完了獅子王,知道有個勇敢堅強的小獅子叫辛巴。

  現在,跨過山和大海,也走過人山人海,經歷了跌跌撞撞,也遭遇了遺憾離別,我們才發現,其實辛巴就是我們每一個自己。

 

  25年前看懂的是劇情,25年後讀懂的卻是人生……

  推薦閱讀:《獅子王》重映語錄

  

                      c#基礎知識詳解系列

 

  歡迎大家掃描下方二維碼,和我一起學習更多的C#知識