上篇對于Model綁定的簡單示範想必大家對Model綁定的使用方式有一點的了解,那大家有沒有想過Model綁定器是在什麼時候執行的?又或是執行的過程是什麼樣的?将在本篇為大家解除這些疑惑,在其中涉及到的一些描述類型和上下文參數會在後續的篇幅中講到。
IModelBinder、自定義Model綁定器簡單實作
Model綁定器在MVC架構中的位置
MVC中的預設Model綁定器生成過程
IModelBinderProvider的簡單應用
IValueProvider在MVC架構中生成的位置以及過程
IValueProvider的應用場景
IValueProvider的實作之NameValueCollectionValueProvider
不廢話直接進入主題,Model綁定器顧名思義是為了Model的綁定提供幫助的這麼一個功能子產品,暫且就這麼了解。Model這裡所指的就是ViewModel,一般都是在控制器方法參數中使用Model,進而使Model綁定器可以使用起來,可是有沒有想過為什麼要這樣用呢?世間的事物都是有因果的,當然這樣的使用方式也逃脫不了,這跟MVC架構中生成Model綁定器的位置是有關系的,我們來看示意圖1。
圖1

看到圖1,可能有的朋友可能覺得很突兀,這裡建議朋友們先去看一下部落客前面所寫過的ASP.NET MVC過濾器系列的文章,看過的朋友肯定就會覺得很熟悉了,但也要考慮沒有看過前面篇幅的朋友。
ControllerActionInvoker類型的InvokeAction()方法是MVC架構中執行控制器方法的必經方法,我們就按照圖1所示的來講解,***的訓示線條為主要流程(雖然不是流程圖)。首先MVC會生成一個ControllerDescriptor類型,然後根據ControllerDescriptor類型再生成ActionDescriptor類型,然後再根據ActionDescriptor類型生成FilterInfo類型的對象,對于ControllerDescriptor類型和ActionDescriptor類型分别表示着控制器描述類型(對象内部包含着控制器的各種資訊)和控制器方法描述類型(同控制器描述類型一個意思),這兩個類型的含義和生成過程後面篇幅會有講解,這裡暫時隻需了解它們代表着什麼就行。
對于FilterInfo類型的解釋是它包含着目前所被調用的控制其方法上的所有過濾器資訊(部落客還是建議朋友們去看ASP.NET MVC過濾器系列的文章),從它的結構中可以看出它包含着各種類型過濾器類型集合對象屬性。
重點來了,從圖1中可以看出MVC架構會先執行授權認證IAuthorizationFilter過濾器,在執行完IAuthorizationFilter過濾器後和執行控制器行為過濾器IActionFilter之前,MVC會根據ActionDescriptor類型擷取到ParameterDescriptor類型的對象【這裡說句題外話看過前面Model中繼資料的朋友,想必知道ParameterDescriptor類型和Model中繼資料的都是用來描述Model的,ParameterDescriptor類型重在描述Model本身,而Model中繼資料更側重于Model的外部修飾,感歎MVC的強大】。
然後再根據ParameterDescriptor類型中ParameterType屬性,表示着Model的類型(Type類型)來生成Model綁定器(IModelBinder),至于生成的細節在下一小節來講解,不能搶樓下的生意。
想必大家現在知道為什麼要把ViewModel放在控制器方法中作為參數來使用了吧。
本小節講解Model綁定器生成的具體過程,也不是太複雜,并且會在後續篇幅控制器方法執行篇幅會将這些知識點全部串聯起來。
現在我們還是先看一下Model綁定器生成的細節吧,圖2
圖2
(黑體字部分表示為屬性名稱,黑體字前面的青色表示屬性類型,而在黑體字上面的表示屬性所屬類型)
按照圖2所示的來講解,首先MVC調用了ControllerActionInvoker類型的GetModelBinder ()方法來生成IModelBinder類型,在方法的内部,MVC首先會判斷參數parameterDescriptor中的BindingInfo屬性中的Binder屬性是否為空,如果為空的話(此部分内容在下篇中會詳解ParameterDescriptor類型,并且以反推的方法來往上講解幾種描述類型),則是調用ControllerActionInvoker類型中的Binders屬性。
現在我們就來看一下Binders屬性的定義,如代碼1-1。
代碼1-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<code> </code><code>protected</code> <code>internal</code> <code>ModelBinderDictionary Binders</code>
<code> </code><code>{</code>
<code> </code><code>get</code>
<code> </code><code>{</code>
<code> </code><code>if</code> <code>(</code><code>this</code><code>._binders == </code><code>null</code><code>)</code>
<code> </code><code>{</code>
<code> </code><code>this</code><code>._binders = ModelBinders.Binders;</code>
<code> </code><code>}</code>
<code> </code><code>return</code> <code>this</code><code>._binders;</code>
<code> </code><code>}</code>
<code> </code><code>set</code>
<code> </code><code>this</code><code>._binders = value;</code>
<code> </code><code>}</code>
從代碼1-1中可以清楚的看到,對于Binders屬性的使用實際是在使用目前系統上下文中的ModelBinders.Binders屬性,這裡先暫停一下,我們看下ModelBinders.Binders屬性中系統給預設提供的綁定器,代碼1-2。
代碼1-2
<code> </code><code>private</code> <code>static</code> <code>ModelBinderDictionary CreateDefaultBinderDictionary()</code>
<code> </code><code>ModelBinderDictionary dictionary2 = </code><code>new</code> <code>ModelBinderDictionary();</code>
<code> </code><code>dictionary2.Add(</code><code>typeof</code><code>(HttpPostedFileBase), </code><code>new</code> <code>HttpPostedFileBaseModelBinder());</code>
<code> </code><code>dictionary2.Add(</code><code>typeof</code><code>(</code><code>byte</code><code>[]), </code><code>new</code> <code>ByteArrayModelBinder());</code>
<code> </code><code>dictionary2.Add(</code><code>typeof</code><code>(Binary), </code><code>new</code> <code>LinqBinaryModelBinder());</code>
<code> </code><code>return</code> <code>dictionary2;</code>
這裡沒有其它的意思,就是讓大家看一下系統預設提供的幾種Model綁定器類型,同樣是使用ModelBinderDictionary類型的Add()方法,唯一不同的就是這是在系統啟動時就會添加生成好的,而我們自定義的Model綁定器則是後面手動添加的。
切回主題,從圖2中我們可以看到在ModelBinderDictionary類型調用GetBinder()方法的時候實際是調用的ModelBinderProviderCollection類型的GetBinder()方法,其實在ModelBinderDictionary類型的内部有着一個ModelBinderProviderCollection類型的字段,再看圖2,在實際調用ModelBinderProviderCollection類型的GetBinder()方法的時候其實真正調用的是IModelBinderProvider類型中的GetBinder()方法。
然而在反編譯工具中也有反編譯不了的,好比ModelBinderProviderCollection類型,我就沒看到它執行個體化的細節,不過沒關系在下一篇中會證明出來它的内部細節。
本篇内容就講解到這,後續的篇幅中會講解如何使用這些類型來實作生成Model綁定器并且進行Model綁定。
本文轉自jinyuan0829 51CTO部落格,原文連結:http://blog.51cto.com/jinyuan/1432203,如需轉載請自行聯系原作者