鏈式編程:泛型實現的擴展方法類


序言

本文分享一個用鏈式編程思想和泛型實現的擴展方法類,用於減少代碼量,並提供更為清晰的業務邏輯代碼表達。

概念

鏈式編程:將多個業務邏輯(方法)通過“.”(點號)串聯起來的一種代碼風格,形似鏈條,故稱鏈式編程。核心思想在於每個方法均返回自身實例。

泛型:可以理解為是一個類的“籃子“”,只要符合約束的類均可以放置在該“籃子”里面。

擴展方法:向現有類添加方法。

根據泛型和擴展方法的特點,泛型+擴展方法實現了向所有符合約束的“類”添加方法,可減少重復代碼量。

(.Net語言提供了這么優雅的特性,剛開始接觸確實讓我“驚為天人”!這也許是我對它深耕不輟的原因吧!)

 背景

筆者在MES系統的多個模塊中,經常要對用戶或方法返回值做判斷,比如以下判斷:

用戶輸入是否為空或空值;

用戶輸入的是否為數字或整數;

用戶輸入的數字是否在正常范圍內;

方法返回的是否為True或False;

......

所以便到處充斥着諸如以下的代碼:

      if (string.IsNullOrEmpty(txtFullScore.Text))
            {
                MessageBox.Show("滿分分數不能為空");
                return;
            }

            if (string.IsNullOrEmpty(txtScore.Text))
            {
                MessageBox.Show("分數不能為空");
                return;
            }

 

作為一個自認為“自我修養”還過得去的程序猿,肯定不允許程序散發“重復代碼的氣味”,

所以實現了泛型+擴展方法實現的鏈式編程風格的類。

特點

該類具有以下優點:

  • 該類采用了泛型,可適用於所用引用類型的擴展;
  • 驗證結果采用委托方法實現,可實現與平台的解耦;
  • 各擴展方法都返回自身實例,可實現邏輯表達上更為清晰的鏈式調用

說明

該類主要分兩部分:直接傳值-擴展方法;委托-擴展方法。

直接傳值-擴展方法

驗證值的獲取方式有兩種:直接獲取和調用方法獲取

方法列表:

  • T IsInt<T>(this T source,string value,Action action
  • T IsNullOrEmpty<T>(this T source, string value, Action action)
  • T IsAllNullOrEmpty<T>(this T source, Action action, params string[] value)
  • T IsNumeric <T>(this T source, string value, Action action)
  • T IsTrue<T>(this T source, bool  IsTrue, Action action)
  • T OPResult<T>(this T source,bool oPResult, Action<bool> action)
  • T Range<T>(this T source, int value, int MinValue, int MaxValue, Action action)

示例代碼

方法描述:驗證字符串是否為空或空值,驗證失敗后執行委托。

     /// <summary>
        /// 驗證是否為空或空值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">返回實例</param>
        /// <param name="value">驗證字符串</param>
        /// <param name="action">驗證失敗后執行該委托</param>
        /// <returns></returns>
        public static T IsNullOrEmpty<T>(this T source, string value, Action action) where T : class
        {
            if (source == null) return null;
            if (!string.IsNullOrEmpty(value)) return source;
            action();
            return null;
        }

 

委托-擴展方法

 

先判斷擴展方法類是否為NULL后才執行委托,避免由於返回的是NULL卻仍然執行委托產生報錯的情況。

方法列表

  • T IsInt<T>this T source, Func<T, string > value,Action action
  • T IsNullOrEmpty<T>(this T source, Func<T, string > value, Action action)
  • T IsNumeric <T>(this T source, Func<T, string > value, Action action)
  • T IsTrue<T>(this T source, Func<T, bool > value IsTrue, Action action)
  • T OPResult<T>(this T source, Func<T, bool > value oPResult, Action<bool> action)
  • T Range<T>(this T source, Func<T,int> value, int MinValue, int MaxValue, Action action)

示例代碼

方法描述:驗證委托的返回值是否為空或空值,驗證失敗后執行委托。

        /// <summary>
        /// 驗證是否為空或空值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source">返回實例</param>
        /// <param name="value">需驗證委托</param>
        /// <param name="action">驗證失敗后執行該委托</param>
        /// <returns></returns>
        public static T IsNullOrEmpty<T>(this T source, Func<T, string> value, Action action) where T : class
        {
            if (source == null) return null;
            if (!string.IsNullOrEmpty(value(source))) return source;
            action();
            return null;
        }

調用示例

現有一個需求判斷分數是否及格,采用WinForm實現。具體需求如下:

滿分不能小於60大於100;分數不能小於等於0;當結果大於等於1時,提示PASS,當結果小於1時,提示NG;當輸入錯誤時,需要提示用戶。

窗體設計如下圖所示:

需求分析

該需求采用如下驗證流程:

→滿分不能為空

→分數不能為空

→滿分必須為整數

→分數必須為整數

→滿分必須在60-100之間

→分數不能小於等於0

→計算結果,結果大於等於0.6,提示PASS,否則提示NG。

一般代碼寫法

            if (string.IsNullOrEmpty(txtFullScore.Text))
            {
                MessageBox.Show("滿分分數不能為空");
                return;
            }

            if (string.IsNullOrEmpty(txtScore.Text))
            {
                MessageBox.Show("分數不能為空");
                return;
            }
            int temp = 0;
            if (!int.TryParse(txtFullScore.Text, out temp))
            {
                MessageBox.Show("滿分必須為整數");
                return;
            }
            if (!int.TryParse(txtScore.Text, out temp))
            {
                MessageBox.Show("分數必須為整數");
                return;
            }
            if (Convert.ToInt32(txtFullScore.Text)<60||Convert.ToInt32(txtScore.Text)>100)
            {
                MessageBox.Show("滿分必須在60-100范圍內");
                return;
            }
            if (Convert.ToInt32(txtScore.Text) < 0)
            {
                MessageBox.Show("分數不能小於等於0");
                return;
            }
            if (Calc(Convert.ToInt32(txtFullScore.Text), Convert.ToInt32(txtScore.Text)))
            {
                MessageBox.Show("PASS");
            }
            else
            {
                MessageBox.Show("NG");
            }

 泛型+擴展方法的鏈式風格寫法

            this.IsNullOrEmpty(txtFullScore.Text,()=> MessageBox.Show("滿分不能為空"))
                .IsNullOrEmpty(txtScore.Text,()=>MessageBox.Show("分數不能為空"))
                .IsInt(txtFullScore.Text,()=>MessageBox.Show("滿分必須為整數"))
                .IsInt(txtScore.Text,()=>MessageBox.Show("分數必須為整數"))
                .Range(t=>Convert.ToInt32(txtFullScore.Text),60,100,()=>MessageBox.Show("滿分必須在60-100范圍內"))
                .IsTrue(t=>Convert.ToInt32(txtScore.Text)>0,()=>MessageBox.Show("分數不能小於等於0"))
                .OPResult(t=>t.Calc(Convert.ToInt32(txtScore.Text),Convert.ToInt32(txtFullScore.Text)),
                (result)=>{if(result) MessageBox.Show("PASS");else MessageBox.Show("NG");});

 

計算結果Calc的代碼如下 

        public bool Calc(int Score, int FullScore)
        {
            return (float)Score / FullScore >= 0.6;
        }

結論

鏈式風格寫法從代碼邏輯上看完全與需求流程一致,邏輯表達上更為清晰。

建議

使用Action委托可以自行設定驗證通過/不通過時所要進行的操作,如MessageShow,也可寫入文件或數據庫,或者其他方法,實現解耦。

建議采用工廠方法實現ActionFactory管理所有的Action委托。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM