Asp.Net Mvc Beta新特性之自動綁定(2)-深入探索篇

來源:互聯網
上載者:User

在上篇中介紹了自動綁定的基本用法,在本篇中,我們將深入瞭解自動綁定的工作原理.

自動綁定的確是讓人感到興奮的特性,然而,為了讓它可以在我們的項目中更好的工作,我們有必要深入瞭解如何更進一步細調該特性以及它是如何工作的.而本文正式即將揭開這個謎底.

為了更好的瞭解該特性,我們有必要到codeplex去下載一份asp.net mvc的原始碼並分析之,在本文寫作的時候,codeplex上已經放上了beta版的源碼,如果想進一步瞭解的朋友可以下載並對照本文分析.

在beta版中,新增了自動綁定這一特性,並對綁定特性做了一定的修改

1.     新增BindAttribute:自動綁定特性設定

2.     修改DefaultModelBinder:自動綁定的實現部分

3.     修改ControllerActionInvoker:綁定的調用入口

4.     新增ModelBinderContext,封裝綁定所需資料

5.     新增BinderResult,封裝綁定結果

其他不大重要的修改略過

    我們一步步來分析綁定的執行過程,首先肯定在ControllerActionInvoker中,看到GetParameterValue方法:

這兒便是對每個參數都嘗試調用ModelBinder來綁定參數,這兒的GetModelBinder方法和P5的一樣,在我們自訂ModelBinder的情況下可以進行自訂綁定,然而在自動綁定的時候擷取的則是DefaultModelBinder,然後在GetPropertyFilter方法中通過查閱BindAttribute來擷取關於綁定的設定.最後對資料進行綁定.

    關鍵的,我們需要對DefaultModelBinder進行分析,然而在此之前,還有一個類也是需要我們仔細看看的,那就是BindAttribute,該特性是用來修飾參數的,它有4個重要的屬性:Include,Exclude,Prefix和一個方法:IsPropertyAllowed,分別用來設定:綁定的欄位,不綁定的欄位,參數首碼和判斷給定的欄位是否設定運行綁定,且該方法會作為一個Predicate委託封入ModelBinderContext傳入BindModel方法.

    現在來討論使用預設綁定的情況,首先給出DefaultModelBinder的所有方法:

分別簡介下這些方法的作用:

1.     BindModel:對外的調用介面,根據傳入的ModelBinderContext綁定值

2.     BindModelCore:綁定自訂類型,自訂類型數組或者自訂類型字典

3.     BindProperty:綁定某個指定的屬性,(此處是一個遞迴調用,仍然調用DefaultModelBinder進行屬性的綁定,也就是說,理論上DefaultModelBinder可以對任意深度的屬性進行綁定)

4.     ConvertSimpleArrayType,ConvertSimpleType,用來做類型轉換,一個轉換數組一個轉換普通類型

5.     CreateArray:建立一個數組對象

6.     CreateModel:建立一個普通對象

7.     CreateSubIndexName:建立子索引名,命名方式為prefix[indexName]

8.     CreateSubPropertyName:建立子屬性名稱,命名方式為prefix.propertyName

9.     GetBinder:擷取modelType的Binder對象

10.   GetElementType:擷取一個類型的ElementType

11.   GetSimeType:對給定的ModelBinderContext進行簡單值綁定(也就是調用該方法時假定擷取的資料是簡單類型)

12.   IsCollectionInserface:判斷是否是數群組類型

13.   IsDictinaryInterface:判斷是否是字典類型

14.   IsSimpleType:是否是簡單類型(在這兒判斷是否是實值型別或者string)

15.   TryUpdateSimpleCollection:嘗試綁定一個簡單數組(即綁定Collection或者Collection,且T能通過IsSimpleType)

16.   UpdateCollection:綁定一個數組,該數組一般為Collection,且T是自訂類型

17.   UpdateDictionary:綁定一個字典類型

通過以上方法的瀏覽,我們發現,DefaultModelBinder可以進行繫結資料很多,包括簡單類型(實值型別和string).自訂類型,數組,字典,同時由於採用了遞迴調用,理論上可以綁定任意深度的資料,由於這兒綁定的調用比較複雜,且本人表達能力有限,本文將不再詳細講述綁定的工作流程,下面將總結下綁定的規則:

1.     預設綁定採用反射的方式將資料繫結到所需對象上

2.     綁定參數有可選特性BindAttribute定義

3.     BindAttribute中可以手動設定允許綁定的屬性或者不允許綁定的屬性,url取參首碼

4.     預設情況下所有屬性都進行綁定

5.     DefaultModelBinder採用遞迴對所有需要綁定的參數進行綁定

6.     普通參數的命名方式為:prefix.protertyName,且預設情況下prefix為類型名.如對象MyData擁有類型為string的屬性Name,那麼在ValueProvider中取值的名稱應該為mydata.name,命名不分大小寫

7.     簡單數組命名方式為prefix.protertyName,其中proertyName為數組名,可以存在多個

8.     對於自訂類型數組和字典,綁定必須提供如下參數:

1.     index-必須提供一個或多個,指示綁定的子項目名,可存在多個

2.     數組必須提供一個或者多個以protertyName[indexName].subProtertyName形式結尾的表單資料,其中protertyName為數組名,indexName為index中定義過的名稱,subProteryName為自訂類型的屬性名稱.

3.     字典必須提供一個或者多個protertyName[indexName].key和protertyName[indexName].value的表單資料,其中protertyName為字典名稱,indexName為index中定義過的名稱,key代表字典中的key綁定,value代表字典中的value綁定,如果key或者value為非簡單類型,表單的定義繼續參照前面.

9.     對於以上綁定,如果子級屬性為複雜類型,可以依次按照此規則命名表單資料

下面我們通過例子來分別描述上面的規則:

    在體驗篇中,我們看到對article的表單命名為article.title,article.content等,這就是根據第6條,父類和屬性用.來間隔,對簡單資料的命名,article.tags,多個同名表單代表多個數族元素,參考第7條,在這兒,如果在article參數中顯式定義了prefix,則需要對應對錶單名進行修改.對於屬性為自訂類型的,繼續使用.間隔,比如上文中的article.advancearticle.today等,此處參考第7,9條,這些部分的例子可以參考第一篇,本篇中將不再說明.

    本篇中將重點介紹自訂類型數組,字典以及多級屬性綁定,下面展示如何綁定一個ICollection,T為自訂類型,比如在AdvanceArticle中添加一個屬性Reads,這是一個自訂類型,包含Name和Source,執行個體代碼如下;

然後根據規則在表單aspx中加入:

這兒給這個數組傳入了兩個元素,分別對應article.reads.index中的0和aa,下面的article.reads[0].name和article.reads[0].source表示第一個元素的子屬性,依次類推.如果您在應用中需要在數組中添加更多元素,可以採用js動態添加表單域的方法,不過每次添加必須對應添加index和對應的子屬性工作表單.

然後是綁定Dictinary,我們在AdvanceArticle中繼續加入新屬性:

然後在aspx中加入表單:

和數組類似的,需要定義article.source.index,此處也顯式定義了兩個字典元素,分別是user和vip(注意,這兒的user和vip並不代表字典key,字典key是需要從表單綁定的),然後分別定義article.source[user].key和article.source[user].key等.如果有更多的元素,也需要按照此規則加入.

同樣的,這兒的key和value也不局限於簡單類型,如果key和value是自訂類型,則可以按照前面的規則繼續向下定義.

最後需要說明幾點: By Leven
2008-10-22

1.     綁定取值不限於表單域,在Beta中加入了ValueProvider,只要是能在ValueProvider中能取到的值都能綁定.

2.     自動綁定是基於反射,如果你嫌效率不夠高,請採用自訂ModelBinder的方式對特定的類型進行特定的綁定已提升效率

3.     自動綁是單向的,如果想實現在route中能接受該參數,可以採用重寫綁定對象的ToString方法輸出對應QueryString的方式,也就是說,如果想在調用Url.Action(“xxx”,new { article= myArticle })能正確傳入傳出參數,可以重寫Article的ToString方法,在提供一個類似article.title=xxx&article.content=xxx的字串格式提供一個協助類,將將資料分別放入ValueProvider,而調用Url方法時採用類似Url.Action(“xxx”,article.ToRouteValue())的方法.

 

By Leven
2008-10-22

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.