2011年11月15日 星期二

[C#] Delegate Event (2)

Delegate Event

上次的目標:
實務上遇到需要計算每家廠商的交易手續費,但是每家廠商計算手續費的方法不同,所以利用Delegate event去指定各家廠商的交易手續費算法(Method)。

這次的目標:
每家廠商下面有多家特店,廠商的手續費是以這些特店的交易筆數(或金額)來計算手續費。
當特店的交易筆數(或金額)有異動時,必須重新計算手續費。

延續上次的專案內容..
一、                Windows Form專案來作範例
1.          專案內容:
2.          Merchant\IMerchant.cs … 廠商Interface
Merchant\CMerchant.cs ...
廠商Class
Store\IStore.cs ...
特店Interface
Store\CStore.cs ...
特店Class
CalFeeMethod.cs ...
手續費計算方法
Form1.cs
3.          執行畫面



二、                這次我們先來看看特店的部分
IStore.cs
1.          程式碼
public interface IStore
       {
        //對應廠商
        CMerchant Merchant { get; set; }
        //特店代號
        String Store_No { get; set; }
        //交易筆數
        double Trans_Cnt { get; set; }
        //交易金額
        double Trans_Amt { get; set; }
       }
2.           比較特別的地方是加入一個CMerchant物件,可以指定某家特店屬於哪家廠商。

三、                CStore.cs
1.          因為要作到「當特店的交易筆數(或金額)有異動時,必須重新計算手續費」這些事情,所以在CStore.cs我們在set Trans_Cnt/ Trans_Amt 時,必須多作一些判斷。
2.          程式碼
public class CStore
    {
        CMerchant cMerchant;  //對應特約機構
        String sStore_No; //特店代號
        double sTrans_Cnt=0; //交易筆數
        double sTrans_Amt=0; //交易金額

         /* 建構子 */
        public CStore(String s_no)
        {
            sStore_No = s_no;
        }
        /* Merchant */
        public CMerchant Merchant
        {
            get
            {
                return cMerchant;
            }
            set
            {
                cMerchant = value;
            }
        }
        /* Store_No */
        public String Store_No
        {
            get
            {
                return sStore_No;
            }
            set
            {
                sStore_No=value;
            }
        }
        /* Trans_Cnt */
        public double Trans_Cnt
        {
            get
            {
                return sTrans_Cnt;
            }
            set
            {
                /*******************************************
                 * 當符合以下情況時,重新統計手續費...
                 * 1. 筆數改變
                 * 2. 原筆數不為0 (表示非第一次設定筆數)
                 * 3. 已指定特約機構 (才知道手續費算法)
                 *******************************************/
                if (sTrans_Cnt != value && sTrans_Cnt != 0 && cMerchant != null) //筆數改變時
                {
                    sTrans_Cnt = value;
                    cMerchant.Print_Fee();
                }
                else sTrans_Cnt=value;
            }
        }
        /* Trans_Amt */
        public double Trans_Amt
        {
            get
            {
                return sTrans_Amt;
            }
            set
            {
                /*******************************************
                 * 當符合以下情況時,重新統計手續費...
                 * 1. 金額改變
                 * 2. 原金額不為0 (表示非第一次設定金額)
                 * 3. 已指定特約機構 (才知道手續費算法)
                 *******************************************/
                if (sTrans_Amt != value && sTrans_Amt !=0 && cMerchant != null) //金額改變時
                {
                    sTrans_Amt = value;
                    cMerchant.Print_Fee();
                }
               else sTrans_Amt = value;
            }
        }
    }
3.          對,沒錯。 我們在筆數(或金額)改變時,偷偷作了一件事情,就是跟廠商說你必須重新計算ㄧ次手續費:cMerchant.Print_Fee()
4.          那廠商怎麼知道所有它底下特店的交易筆數和金額呢? 所以Merchant介面/類別需加上一點東西。
四、                IMerchant.cs
1.          程式碼

       public delegate void CalFeeHandler(double dFee_Pt, double dNum);
       public delegate void CalFeeHandler(double dFee_Pt, double dCnt, double dAmt);


       public interface IMerchant
       {
        //特約機構代號
        String Merchant_No {get; set; }
        //底下所有特店
        List<CStore> StoreList { get; set; }
        //手續費
        double Fee_Pt { get; set;  }
        //計算手續費的事件
        event CalFeeHandler CalFee;
       }

2.          灰底的部分就是這次新增的程式碼
將計算手續費的delegate,傳入值分成三個:
 
dFee_Pt (手續費趴數)dCnt (筆數) dAmt(金額)
新增一個List<CStore>物件,可以紀錄在這家廠商底下的所有特店(CStore

 
五、                CMerchant.cs
1.          至於廠商類別的部分,也是作ㄧ些調整,故指列出調整的程式碼。
get/set 特店 以及 觸發計算手續費的方法 (灰字的程式碼為修改前的程式碼)
2.          程式碼
public class CMerchant : IMerchant
    {
        List<CStore> lStoreList;


        /* StoreList */
        public List<CStore> StoreList
        {
            get
            {
                return this.lStoreList;
            }
            set
            {
                this.lStoreList = value;
            }
        }


        /* 觸發CalFee這個Event */
        public void Print_Fee(double dNum)
        {
            if (CalFee == null)  //未指定手續費時...
            {
                Console.WriteLine("未指定手續費計算事件!");
            }
            else  // CalFee 這個delegate event計算手續費
            {
                CalFee(dFee_Pt, dNum);
            }
        }
/* 觸發CalFee這個Event */
        public void Print_Fee()
        {
            if (CalFee == null//未指定手續費時...
            {
                Console.WriteLine("未指定手續費計算事件!");
            }
            else  // CalFee 這個delegate event計算手續費
            {
                if (StoreList != null)
                {
                    double dCntSum = 0;
                    double dAmtSum = 0;
                    foreach (CStore myStore in StoreList)
                    {
                        dCntSum += myStore.Trans_Cnt;
                        dAmtSum += myStore.Trans_Amt;
                    }
                    CalFee(dFee_Pt, dCntSum, dAmtSum);
                }
            }
        }

    }

3.          程式這樣一對照,應該馬上就看出差別了。 之前我們是傳入一個交易筆數或金額讓Print_Fee() 觸發計算手續費事件(CalFee) 這一次我們不傳入任何值,而是讓這家廠商自己去統計它底下所有特店的交易筆數和金額,再傳給delegate event(CalFee)計算手續費。

六、                CalFeeMethod.cs
1.          實作delegate event的手續費演算法沒有更動,只是配合delegate event的傳入參數變成三個:
        /* 手續費 = 交易筆數*手續費趴數 */
        public static void CalFee_by_TransCnt(double dFee_Pt, double dCnt, double dAmt)
        /* 手續費 = 交易金額*手續費趴數/100 */
        public static void CalFee_by_TransAmt(double dFee_Pt, double dCnt, double dAmt)


七、                Form1.cs
1.          接下來就是直接拿來用了,底下用一個ListBox放三家廠商的代號,當按下「算手續費」按鈕時,就會計算各家廠商的手續費。




2.          就不多作解說了流程大致如下
a.
建立廠商(CMerchant)
b.
建立多家特店(CStore),並指定上層廠商。
c.
上層廠商加入這些特店
d.
廠商作第一次統計手續費
e.
當某廠商下任一家特店筆數/金額改變時,會重新統計該廠商的手續費。

3.          程式碼
private void bt_CalFee_Click(object sender, EventArgs e)
        {
            int MerchantCnt = lb_Mno.Items.Count;
            CMerchant[] MerchantSet = new CMerchant[MerchantCnt ];

            for (int index = 0; index < MerchantCnt; index++)
            {
                String sM_NO = lb_Mno.Items[index].ToString();

                MerchantSet[index] = new CMerchant(sM_NO);
                Console.WriteLine("特約機構代號:" + MerchantSet[index].Merchant_No);

                List<CStore> myStores = new List<CStore>(0);

                CStore storeA = new CStore("A");
                storeA.Merchant = MerchantSet[index];
                storeA.Trans_Cnt=10;
                storeA.Trans_Amt = 100;

                CStore storeB = new CStore("B");
                storeB.Merchant = MerchantSet[index];
                storeB.Trans_Cnt=20;
                storeB.Trans_Amt = 200;

                myStores.Add(storeA);
                myStores.Add(storeB);

                MerchantSet[index].StoreList = myStores;
               
                switch (sM_NO)
                {
                    case "123456":
                        MerchantSet[index].Fee_Pt = 0.8;
                        MerchantSet[index].CalFee += CalFeeMethod.CalFee_by_TransCnt;
                        break;
                    case "888888":
                        MerchantSet[index].Fee_Pt = 0.5;
                        MerchantSet[index].CalFee += CalFeeMethod.CalFee_by_TransAmt;
                        break;
                    default:
                        MerchantSet[index].Fee_Pt = 0;
                        break;
                }

                //列印手續費
               MerchantSet[index].Print_Fee();

                //改變storeA的筆數和金額
                //storeA.Trans_Cnt = 30;
                storeA.Trans_Amt = 100;

                Console.WriteLine("");
            }

        }

八、                執行結果
特約機構代號:123456
手續費 = 交易筆數*手續費%=24
手續費 = 交易筆數*手續費%=40

特約機構代號:888888
手續費 = 交易金額*手續費%/1001.5
手續費 = 交易金額*手續費%/1001.5

特約機構代號:333333
未指定手續費計算事件!
未指定手續費計算事件!



沒有留言:

張貼留言