<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      代碼改變世界

      盡可能地使用強類型數據

      2009-02-27 08:19  Jeffrey Zhao  閱讀(21218)  評論(69)    收藏  舉報

      我們繼續來談《最佳實踐》,這次的主題便是“強類型”。

      一直說C#是強類型語言,通俗地講,便是指C#中的“變量”在開發時的類型便是明確的:String便是String,Int32就是Int32,毫無爭議。強類型的好處有很多,張嘴便可隨意舉上幾例:

      • 能夠享受代碼提示功能
      • 能夠獲得重構工具的支持
      • 能夠在編譯期發現更多錯誤
      • ……

      不過C#也不是“絕對”的強類型語言,因為它也有弱類型,那就是Object。我們知道Object是所有類型的最終基類,任何類型的對象都可以使用Object來引用。可是一旦轉化成Object的變量之后,代碼提示便消失了;即使我們“明確”對象的確切類型,也必須通過Cast才能使用——更何況它形成了一種被“濫用”或“誤用”的機會。例如一段錯誤代碼可能會傳入一個不符合約定類型的對象,那么就會造成錯誤。更嚴重的是,這樣的錯誤可能只要在“運行時”才能被發現,編譯器對此無能為力。

      類似的“實踐”其實很多,例如“方法盡可能接受抽象的類型,而返回具體的類型”。

      ASP.NET MVC中對于“強類型”一說最典型的方面便是視圖。在ASP.NET MVC中每種視圖(View,Partial,Layout)都可以選擇弱類型和強類型兩種“基類”,兩者的區別便是Model的類型。強類型視圖的唯一區別便是其Model屬性為范型參數所指定的類型——而弱類型則自然就是Object了。在這里我提出一個“最佳實踐”:總是使用強類型的視圖,并且所有數據都從Model中獲取。這么做可能會在一定程度上增加了代碼量,因為我們需要為每個視圖建立一個Model,不過我認為這是值得的。在強類型的視圖中,VS中能夠對Model的各種成員做出豐富的代碼提示,我們便可以快速地輸入代碼,并確保不會出現“拼寫”之類的低級錯誤。如果使用了ViewData這個弱類型的字典,那么每次我們獲取某個值之后,都必須將其Cast成具體的類型才能使用,這無疑使視圖模板變得復雜而難以維護。

      其實以上的準則還有另一個層面的內容。使用項目模板安裝了ASP.NET MVC之后,在~/Views/Shared/LogOnUserControl.ascx文件中可以發現對Page.User屬性的直接訪問。這自然可以運行,但是其帶來的后果是“弱化”了aspx/ascx/master文件的“模板”概念,而重新讓其意識到“我是一張頁面”。在ASP.NET MVC框架中,我們要時刻記著“項目中沒有頁面”,我們始終使用Controller中的Action方法來處理請求,而每個請求需要對應一個磁盤上“物理文件”的思維方式一定需要改變(無論是在用WebForms模型還是MVC模型)。直接訪問Page.User屬性也使我們很難為視圖進行獨立的單元測試,因為視圖與HttpContext直接耦合,而HttpContext的Mock相當困難。

      在《最佳實踐》的示例中,我為每個視圖都構建了一個Model,它們都在MyMvcDemo.Web.UI.Models項目中。值得一提的是,由于業務的需要,視圖之間很可能出現“數據共享”。例如View和Layout(更ASP.NET的說法是Page與Master Page)之間共享同一個Model。更進一步,兩者之間其實是多對多的關系,如果我們為每個ViewPage定義了強類型的Model,又如何應對同一個ViewPage套用不同ViewMasterPage的情況呢?這個問題最自然的解決方式便是使用接口。一個Model對象不可以有多個父類,但是完全可以實現多個接口。因此,我們往往為強類型的ViewMasterPage指定一個接口作為其泛型參數。從示例中您也可以發現,Site.Master的類型為ViewMasterPage<ISiteMasterModel>,而每個ViewPage的Model類型都實現了ISiteMasterModel接口。

      使用ViewData的另一個壞處是必須使用字符串作為鍵進行訪問。字符串是什么?是常量。分散在各處的常量是維護性的大敵,而使用ViewData則幾乎無可避免地將字符串常量分散在控制器和視圖兩個地方——您可能會覺得,使用枚舉不就解決這個問題了嗎?如果這么做,相當于為每個視圖定義不同的枚舉類型,那么我們為什么不直接構造強類型的Model呢?使用字符串作為鍵的另一個壞處是無法在編譯期發現問題:如果您一不小心拼寫錯誤了怎么辦呢?您可能會覺得,原本aspx就必須到運行時才會動態編譯,不過現在ASP.NET MVC的模板已經增加了相關的MSBuild Task,或者使用ASP.NET的預編譯功能,都可以在編譯時對視圖進行檢查了。這也是我建議大家使用aspx,而不是另一種DSL來構建視圖的原因——aspx的周邊支持實在是太豐富了。

      不過在視圖中,字符串常量并非只出現在ViewData的訪問上。例如,使用ASP.NET MVC框架模板創建項目之后,Site.Master中生成導航欄鏈接的代碼是這樣的:

      <ul id="menu">              
          <li><%= Html.ActionLink("Home", "Index", "Home")%></li>
          <li><%= Html.ActionLink("About", "About", "Home")%></li>
      </ul>
      

      代碼使用了Html.ActionLink這個輔助方法生成一個導向至某個Action的鏈接,只可惜這里又出現了字符串參數表示的Controller名和Action名。事實上,如果您下載了ASP.NET MVC RC的源代碼之后,能夠發現其中的MvcFutures項目中包含了“強類型”的ActionLink輔助方法,于是我們的代碼就能修改為如下模樣(參見《最佳實踐》的示例):

      <li><%= Html.ActionLink<HomeController>(c => c.Index(), "Home") %></li>
      <li><%= Html.ActionLink<HomeController>(c => c.About(), "About") %></li>
      <li><%= Html.ActionLink<AccountController>(c => c.Register(), "Register") %></li>
      <li><%= Html.ActionLink<AccountController>(c => c.List(1), "Admin") %></li>
      

      這下我們便可以使用Lambda Expression這個強類型的表示方法來“告訴”ActionLink方法究竟該生成導向至哪個Action方法的鏈接。甚至我們可以在“調用”Action方法的同時指定其參數——例如最后一行代碼,指定將查看“第一頁”內容,而這些數據在交給URL Routing的配置后便能得到我們想要的URL。MvcFutures中還定義了其他類似的輔助方法,例如UrlHelper中的輔助方法則會直接生成一個URL鏈接——而不是一個<a />元素。可惜目前MvcFutures中的這些輔助方法編寫的并不完全“正確”,因為它直接把方法名作為Action的名稱來使用,而ASP.NET MVC從某個預覽版開始引入了ActionNameAttribute,可以為一個Action方法指定一個不同的Action名稱。因此如果您使用ActionNameAttribute來改變Action名,則很可能您需要構建自己的輔助方法。不過這條準則依舊成立:使用強類型的表示法生成URL地址

      如果您要使用MvcFutures中的內容,則必須自行編譯MvcFutures項目。有一點值得注意,如果您使用直接編譯ASP.NET MVC RC解決方案所得到的Microsoft.Web.Mvc.dll,就會發現它依賴的是“System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”,而您開發時所使用的,也就是安裝在系統中的程序集是“System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35”,兩者不同自然難以兼容。幸運的是,您只要手動修改一下MvcFutures項目的程序集引用就可以了,對您來說這一定不是問題。

      看到這里,不知道您是否發現了一個比較“嚴重”的問題,其嚴重程度大大降低了這些負責生成URL的輔助方法的可用性。這是個什么問題呢?又該如何解決呢?我在這里先賣個關子,下個星期我將公布這個問題,以及它的解決方法——這部分內容并沒有包含在上次《最佳實踐》的講座中,算是一個“保留節目”吧。:)

      主站蜘蛛池模板: 公天天吃我奶躁我的在线观看| 精品国产一区二区三区久久女人 | 国产中文字幕精品在线| 女女互揉吃奶揉到高潮视频| 韩国无码AV片午夜福利| 在线播放亚洲成人av| 亚洲大尺度无码无码专线| 精品亚洲国产成人av| 麻豆av一区二区天美传媒| 久久一亚色院精品全部免费| 乱老年女人伦免费视频| 国产乱码精品一区二区三| 国产最大成人亚洲精品| 久久天天躁狠狠躁夜夜2020老熟妇| 午夜成人无码福利免费视频| 午夜福利在线观看6080| 国产精品国产三级国产试看| 人妻丰满熟AV无码区HD| 亚洲一区精品视频在线| 亚洲精品一区二区三区小| 日韩av一区二区三区不卡| 熟女一区二区中文在线| 91国产自拍一区二区三区| 内地偷拍一区二区三区| 91亚洲国产三上悠亚在线播放| 伊人春色激情综合激情网| 午夜成人无码免费看网站| 国产三级精品三级在专区| 国产成人亚洲精品狼色在线| 国产粉嫩系列一区二区三| 大战丰满无码人妻50p| 尉氏县| 精品一区二区三区日韩版| 国产精品亚洲中文字幕| a片在线免费观看| 三级4级全黄60分钟| 色猫咪av在线网址| 凤山县| 国产精品综合色区在线观| 少妇高潮太爽了在线视频| 亚洲精品美女久久久久9999|