Asp.Net MVC雜談之:—步步打造表單驗證架構(2)

來源:互聯網
上載者:User

    題外話:為了不再誤解,關於造輪子的事情在本篇開頭再次重點提出,如果您覺得再造輪子的人是傻瓜,那直接無視我以及我的附帶品好了.本文的重點並不是做了一個驗證架構,真要如此,直接給出代碼不就結了,或者直接來篇如何使用DataAnnotations即可,何必長篇大論來一通,如果認真看了本文就可以知道本文是講解了如何使用TDD的方法來實現一個驗證架構,同時儘可能做到通俗易懂,當然,這並不是說本文造的輪子就沒有價值了,別人的總是別人的,驗證架構並不是一個很複雜的東西,一個人做出一個完善的也不是什麼難事,也許在某些時候土炮就比洋炮好用也說不準,最後,希望各位手下留情.
    說了一通廢話,下面開始本文了,本篇的重點是解決前篇的代碼靈活性問題,前一篇我們對實現了兩個驗證屬性,但是確遇到了新的問題,方法中代碼量的激增以及死板的驗證方式無法讓我們靈活的擴充該架構,窮則變,變則通,我們不得不想辦法解決這個問題,從目前的代碼看,實體的Validate方法明顯有問題,它的責任明顯太多,勢必要對其進行重構,要把它的責任分離出去,如何分離呢?
    我們完全可以這樣考慮,現在的驗證屬性僅僅申明了驗證參數,而且如果有很多屬性參數也會不同,驗證的模式也各不相同,那為什麼不讓驗證屬性自食其力,自力更生呢?自己的限制,自己驗證多好.因此考慮擴充驗證屬性的功能,既然驗證是一種契約,一種公用行為,我們免不了設計一個介面來負責這部分的內容,考慮下面的介面:

    這樣一來我們就可以在xxxAttribute中實現相應的驗證邏輯了,首先確定新的驗證代碼,對3個屬性進行全面驗證測試:

    然後我們開始重構RangeAttribute和RequiredAttribute類,下面的圖片分別展示了兩個屬性中的驗證邏輯


    最後修改Student部分的驗證方法,來通過調用xxxAttribute的Validate方法實現各個屬性的驗證

    然後執行測試代碼-通過,很慶幸我們的重構完成的很好,這樣一來,只要是實現了IValidationFIlter的驗證屬性都可以自動的進行驗證了(到此為止的代碼請參考Leven.Validate04).
    下面考慮另外一個問題,現在我們的驗證方法是寫在Student實體中的,不妨考慮如果我們有另外一個Teacher實體那該如何?難道又要在Teacher實體中把這個方法copy過去麼?這顯然不是一個好辦法,我們不得使用一種方式將這段代碼提取出來,這樣一來可以考慮以下兩種方式:
1. 既然每個實體都要有這個方法,則可以對實體物件進行抽象,在其頂端實現公用基類,在基類中實現該方法
2. 完全不修改實體物件,另外建立方法(靜態方法??擴充方法??)來進行驗證
    對比以上兩種方式,可以預見,第二種方式能建立更廣泛的驗證,也就是說,它可以對Object進行驗證,當然前提是該Object中有屬性添加了驗證Attribute(沒添加也不要緊,這樣驗證永遠都會成功),因此,使用第二種方式的驗證可以用在任何對資料效驗的環境下(實際上, DataAnnotations等不限場合的驗證架構都使用這種方式)而第一種方式看起來會對實體本身進行要求,必然產生了局限性,然而,我們現在要考慮的是表單實體,也就是說可能在必要的時候能和Asp.Net MVC架構能夠整合在一起,這本身就是一個限制了,因此,第一種方式也不失為一種不錯的選擇,這樣一來,我們就限定了只有部分我們需要的實體能享受該功能.同時如果以後在和MVC架構整合的時候不需要考慮更多的情況,所以目前決定了,就使用第一種方式了.
    首先仍然是確定介面,一個必須的IValidationEntity介面,然後針對該介面必須有一個預設的實現ValidationEntityBase,具體實現步驟如下:
1. 新增IValidationEntity介面,介面中包含一個Validate方法
2. 新增一個ValidationEntityBase類,實現IValidationEntity介面.
3. 將Student的Validate方法代碼搬到ValidationEntityBase的Validate方法中
4. 建立單元測試,測試代碼和先前一致
5. 開始測試,保證測試通過
    通過這幾步,我們成功對實體進行重構,如果我們新增任意實體,只要繼承自ValidationEntityBase,就可以享受到驗證的好處了,在項目Leven.Validate05中,可以看到完成後的原始碼,同時,實現了新的實體Teacher,並進行了測試.
    小結:我們回過頭來看看架構一步步的重構過程,從目前來看,前面幾次重構都是針對擴充性進行的,這正是架構和普通程式的根本區別,架構考慮的一般化,因此,我們一步步的實現了幾個目標:
1. 第一次完成的代碼,就實現了實體的屬性中可以有任意多個驗證Attribute
2. 第一次重構,實現實體的每個屬性都可以有任意多個驗證Attribute
3. 第二次重構,實現了實體的每個屬性都可以有任意多個目前支援的兩種驗證Attribute
4. 第三次重構,分離驗證職責,加入驗證Attribute擴充功能,,使得實體的每個屬性都可以有任意多個實現了IValidationFilter的驗證Attribute
5. 第四次重構,轉移驗證方法,加入IValidationEntity介面,使得任意實現IValidationEntity介面的實體的每個屬性都可以有任意多個實現了IValidationFilter介面的驗證Attribute.
    到現在為止,才算是真的有點像架構了,上面的5次編碼過程,雖然說起來比較繞口,但是仔細看來,正是將功能一步步泛化的過程.真正實現了驗證架構的兩個重要目標:1.能擴充規則,2.為需要驗證的對象提供驗證服務,同時區分哪些是需要驗證的對象.
    到目前為止的類圖如下:


    現在看來,架構似乎可以滿足我們的要求了,那是不是已經完美了呢?當然不是,如果真要在實際中使用,還有很多其他的因素要考慮,首先,我們在驗證Attribute定義了錯誤資訊,但是目前我們驗證完成之後只得到一個bool值,沒法得到相對應的驗證資訊,其次,目前架構使用的是反射來對資料效驗,然而反射的效率總是人們覺得不爽的地方,在下一篇中,我們將著重解決這幾個問題.
    最後給出專案檔:/Files/leven/LevenValidateLibrary02.rar

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.