Util應用程序框架公共操作類(一):數據類型轉換公共操作類(介紹篇)


  本系列文章將介紹一些對初學者有幫助的輔助類,這些輔助類本身並沒有什么稀奇之處,如何能發現需要封裝它們可能更加重要,所謂授之以魚不如授之以漁,掌握封裝公共操作類的技巧才是關鍵,我會詳細說明創建這些類的動機和思考過程,以幫助初學者發現和封裝自己需要的東西。創建公共操作類的技巧,大家可以參考我的這篇文章——應用程序框架實戰十二:公共操作類開發技巧(初學者必讀)

  封裝公共操作類,不僅要把技術上困難的封裝進來,還需要不斷觀察自己的代碼,以找出哪些部分可以更加簡化。本文將介紹一個容易被大家所忽視的東西——數據類型轉換。

  數據類型轉換可以把某個源類型轉換為目標類型,比如把字符串轉換為整型。一種選擇是,你可以使用System.Convert類進行轉換。  

string input = "1"; int result = System.Convert.ToInt32( input);

  這樣看起來好像沒什么問題,不過input很明顯不一定是個常量,如果你還在使用ASP.NET Web Form這樣的技術,你需要在后置代碼中從控件讀取值。

string input = TextBox1.Text; int result = System.Convert.ToInt32( input);

  當客戶輸入整數時,不會有什么問題,但他如果輸入一個字母或漢字,上面代碼會拋出一個異常,“System.FormatException: 輸入字符串的格式不正確。”,這可能不是你想要的。當然,你可以在客戶端進行JS驗證,不過客戶也可以繞過你的頁面,直接POST到你的服務器,所以你在服務端必須處理這個問題。

  引發異常,並且你沒有進行任何處理,可能導致一個黃頁,讓你的客戶一驚。為了避免顯示黃頁,初學者大多直接在代碼上加一個try-catch進行捕獲,並給客戶一個友情提示。

try {   string input = TextBox1.Text;   int result = System.Convert.ToInt32( input ); } catch( Exception ex ) {   //彈出消息框提示客戶輸入正確數據 }

  一旦吃到甜頭,初學者發現這段代碼可以實現他要的功能,不會過多考慮可維護性,於是會把這個結構向整個表現層復制,最終導致一個混亂的局面。

  除了表現層以外,數據訪問層也經常需要進行數據類型轉換。如果你還在使用原始的Ado.Net,從DataReader獲取值。

IDataReader reader = cmd.ExecuteReader(); int result = System.Convert.ToInt32( reader["字段名"] );

  同樣,為了不引發異常,初學者根據之前的經驗,會在調用代碼時添加try-catch進行異常捕獲。

try {   IDataReader reader = cmd.ExecuteReader();   int result = System.Convert.ToInt32( reader["字段名"] ); } catch( Exception ex ) {   //有些人會在這里記錄錯誤日志,還有些懶人直接留空,啥也不干
}        

  所以最終的結果是,只要進行數據類型轉換的操作,初學者為了一定的系統健壯性會大量添加異常處理結構,從而導致代碼混亂。

  另一個選擇是,.Net提供了一個不引發異常的類型轉換方法,比如,

string input = "1"; int result; if( int.TryParse( input, out result ) == false ){   //處理錯誤
}

  TryParse會返回一個bool值,指示轉換是否成功,如果轉換失敗,你可以記錄日志,並顯示一個錯誤。不過大部分人都可能會偷懶,不會在這里進行任何處理。

string input = "1"; int result; int.TryParse( input, out result );

  如果你不想引發異常,更不想用try-catch結構來捕獲異常,這確實是一個更好的選擇,但需要額外定義一個變量,作為out參數來獲取值,會造成額外的工作量。

  當然,.Net技術也一直處於持續改進中,表現層技術進入到MVC和WPF時代,而數據訪問技術也進入到了Entity Framework時代。MVC提供了一個叫做模型綁定的功能,用於將界面上傳回的數據映射到控制器操作的參數中,並且這些參數可以支持實體,這是一個非常強大的功能,這樣就不需要手工進行賦值了,更不需要類型轉換。WPF通過雙向數據綁定,Entity Framework通過映射器,都解決了類似問題。

  但是,並不是說數據類型轉換就毫無用武之地了,考慮一個使用MVC的場景。你在界面上有一個表格,表格的每行都有一個checkbox,你可以打勾以選中某些行,然后你會把每行的實體標識傳到控制器。如果實體標識的數據類型使用Guid,你可以用一個IList<Guid>來接收。

public ActionResult 方法名( IList<Guid> ids ) { }

  這一般都行得通。但是,你並不總是可以這樣干,出於某些特殊原因,有時候你需要自己在js中用逗號拼接一些Id,或者用一個Hidden把用逗號拼接的Id保存起來,然后作為一個字符串傳到控制器。比如” 06d8dcdd-cfad-433c-aec0-87bf613b9457, 684c0c02-93ec-4047-8f16-57e36b50d703”。

public ActionResult 方法名( string ids ) { }

  由於沒有自動轉換支持,你只好自己動手,這很簡單,使用逗號把輸入字符串打散成字符串數組,然后遍歷每個數組元素,轉換成Guid類型,再添加到一個結果集合保存起來就OK了。

public ActionResult 方法名( string ids ) {   List<Guid> result = new List<Guid>();   string[] list = ids.Split( ',' );   foreach( var each in list ) {     result.Add( Guid.Parse( each ) );   }   //在這里把result傳到業務層
}

  你發現這段代碼不僅可以處理帶有逗號的字符串,像” 06d8dcdd-cfad-433c-aec0-87bf613b9457, 684c0c02-93ec-4047-8f16-57e36b50d703”,甚至還能處理不帶逗號的,比如“06d8dcdd-cfad-433c-aec0-87bf613b9457 “。你非常滿意,然后把這一段代碼復制到所有需要將拼接字符串轉換成集合的地方。

  沒過多久,你在一個頁面發現了Bug,以前測試的時候,都是操作多個Id,這次沒進行操作,傳過來的字符串是””,你的代碼沒有進行任何健壯性檢測,所以失敗了,拋出一個異常“無法識別的 GUID 格式。“。

  你安慰自己“這並不算什么技術問題,只是一時疏忽,看我加一個判斷,一招將它搞定“。不過在你的下意識里,已經感覺到進行邊界測試才是健壯性的關鍵。

public ActionResult 方法名( string ids ) {   List<Guid> result = new List<Guid>();   if ( !string.IsNullOrWhiteSpace( ids ) ) {     string[] list = ids.Split( ',' );     foreach( var each in list ) {       result.Add( Guid.Parse( each ) );     }   }   //在這里把result傳到業務層
}

  你現在准備測試一下,傳了一個””過來,果然有效,你大贊自己處理BUG的速度驚人,為了給其它地方也添加如此健壯的特性,你打開所有可能用到的頁面,找到這幾行代碼,進行修改,雖然你感覺這確實有點無聊,但還是只有硬起頭皮改了。

  從上面可以看到,雖然是司空見慣的數據類型轉換,也還是有很多值得我們改進的地方。

  下一篇我將使用TDD方式把數據類型轉換公共操作類開發出來。由於TDD並不是本系列介紹的重點,所以我不會在本文中詳細介紹TDD的要點,請大家查看相關資料,如果有空,我會專門寫一篇文章來分享我在使用TDD所碰到的障礙以及心得。

  .Net應用程序框架交流QQ群: 386092459,歡迎有興趣的朋友加入討論。

  謝謝大家的持續關注,我的博客地址:http://www.cnblogs.com/xiadao521/


免責聲明!

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



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