溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

ASP.NET MVC Model元數(shù)據(jù)(二)

發(fā)布時(shí)間:2020-08-07 22:44:48 來(lái)源:網(wǎng)絡(luò) 閱讀:835 作者:jinyuan0829 欄目:編程語(yǔ)言

ASP.NET MVC Model元數(shù)據(jù)(二)

前言

在上篇中,給大家留個(gè)對(duì)Model元數(shù)據(jù)的印象,并沒(méi)有對(duì)Model元數(shù)據(jù)有過(guò)多的講解,而在本篇中也不會(huì)對(duì)Model元數(shù)據(jù)的本身來(lái)解釋,而是針對(duì)于它的生成過(guò)程,讓大家能夠清楚的了解到系統(tǒng)框架是在什么時(shí)候生成Model元數(shù)據(jù)的,對(duì)于Model元數(shù)據(jù)生成篇幅初定為兩篇,本篇為它的整體的生成過(guò)程,下篇?jiǎng)t為詳細(xì)的生成過(guò)程并且會(huì)對(duì)它本身做一個(gè)粗略的介紹,希望大家看完能夠有所收獲

 

Model元數(shù)據(jù)

  • 什么是Model元數(shù)據(jù)?

  • 生成Model元數(shù)據(jù)的過(guò)程【一】

  • 生成Model元數(shù)據(jù)的過(guò)程【二】

  • ModelMetaData的定義、詳解

  • Model元數(shù)據(jù)應(yīng)用(常用特性應(yīng)用)-1

  • Model元數(shù)據(jù)應(yīng)用(自定義視圖模板)-2

  • Model元數(shù)據(jù)應(yīng)用(IMetadataAware接口使用)-3

 

生成Model元數(shù)據(jù)的過(guò)程【一】

還是如前篇說(shuō)的那樣,既然叫Model元數(shù)據(jù)(Model指的是視圖模型)那么肯定跟Model有關(guān)系了,而在我們MVC項(xiàng)目中一般是什么時(shí)候會(huì)對(duì)Model進(jìn)行操作呢?一般情況下都是在通過(guò)控制器的行為請(qǐng)求一個(gè)視圖的時(shí)候,而控制器行為的參數(shù)即為Model,然后在行為方法中做一些處理然后再傳遞給視圖。然后再根據(jù)上篇最后的一個(gè)示意圖來(lái)看,

圖1

 ASP.NET MVC Model元數(shù)據(jù)(二)

生成Model元數(shù)據(jù)的地方已經(jīng)鎖定到了行為方法,想象一下肯定是不可能在行為方法中來(lái)生成的,因?yàn)槟鞘俏覀冏远x邏輯的地方。那是在什么地方呢?

想必大家看過(guò)之前的對(duì)過(guò)濾器篇幅的介紹,在ASP.NET MVC 過(guò)濾器(三)中對(duì)行為過(guò)濾器的執(zhí)行過(guò)程講解的時(shí)候,中間有提到過(guò)模型綁定器,并且說(shuō)到了系統(tǒng)框架所要使用到的自定義模型綁定器,而使用這個(gè)自定義模型綁定器所需要的兩個(gè)參數(shù)是非常重要的,一個(gè)是表示當(dāng)前控制器上下文的對(duì)象ControllerContext,另一個(gè)則是生成Model元數(shù)據(jù)的關(guān)鍵,也是調(diào)用自定義模型綁定器的關(guān)鍵參數(shù)ModelBindingContext類型??聪?/span>

圖2

ASP.NET MVC Model元數(shù)據(jù)(二)

 

而在ModelBindingContext類型中有個(gè)重要的屬性,即為Model元數(shù)據(jù)類型ModelMetadata,由此可以知道在我們的控制器行為執(zhí)行之前,對(duì)應(yīng)控制器行為的Model的Model元數(shù)據(jù)ModelMetadata類型已經(jīng)生成了。(這部分內(nèi)容詳見(jiàn)過(guò)濾器篇幅)

而它是怎么生成的呢?是通過(guò)系統(tǒng)框架中默認(rèn)提供的提供程序來(lái)生成的,是哪些個(gè)類型呢?

圖3

ASP.NET MVC Model元數(shù)據(jù)(二)

那我們就先看一下最頂層的基類ModelMetadataProvider的定義:

代碼1-1

public abstract class ModelMetadataProvider
    {
        // 摘要:
        //     在派生類中重寫時(shí),初始化派生自 System.Web.Mvc.ModelMetadataProvider 類的對(duì)象的新實(shí)例。
        protected ModelMetadataProvider();
        public abstract IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType);
        public abstract ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
        public abstract ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
    }

 

非常明白的定義,三個(gè)抽象方法,這里我們只需先看GetMetadataForType()方法,其它兩個(gè)暫時(shí)不管下篇中會(huì)有講到,因?yàn)橄瓤碐etMetadataForType()方法呢?因?yàn)樗巧?strong>ModelMetadata類型的入口,第一個(gè)參數(shù)暫時(shí)忽略,第二個(gè)參數(shù)嘛很重要了,是ParameterDescriptor類型的ParameterType屬性,表示著Model的類型(也就是控制器方法參數(shù)的Type類型),現(xiàn)在我們來(lái)看下圖4

圖4

ASP.NET MVC Model元數(shù)據(jù)(二)

 

圖4中藍(lán)色線條為主要流程,紅色線條是在藍(lán)色處理之后執(zhí)行的流程。

上面說(shuō)到,入口方法是為抽象方法,那是怎么具體實(shí)現(xiàn)的呢,從圖4中可以看到是由實(shí)現(xiàn)了ModelMetadataProvider的類型AssociatedMetadataProvider類型來(lái)進(jìn)行處理的,從圖4可以看到首先是獲取一個(gè)AttributeList的類型,AttributeList類型表示著從AssociatedMetadataProvider類型GetMetadataForType()方法參數(shù)modelType類型上的特性集合,對(duì)了AssociatedMetadataProvider類型是比較重要的類型,我們先來(lái)看一下它的定義:

public abstract class AssociatedMetadataProvider : ModelMetadataProvider
    {
        protected AssociatedMetadataProvider();
        protected abstract ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName);
        protected virtual IEnumerable<Attribute> FilterAttributes(Type containerType, PropertyDescriptor propertyDescriptor, IEnumerable<Attribute> attributes);
        public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType);
        protected virtual ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, PropertyDescriptor propertyDescriptor);
        public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
        public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
        protected virtual ICustomTypeDescriptor GetTypeDescriptor(Type type);
    }

方法有點(diǎn)多,暫時(shí)不用管,大多數(shù)方法都是用來(lái)在遞歸生成Model元數(shù)據(jù)的時(shí)候使用的(具體的過(guò)程會(huì)在下篇中講解)。好了切回主題接著上面的內(nèi)容來(lái)說(shuō),AttributeList類型的由來(lái),是通過(guò)ModelMetadataProvider的GetTypeDescriptor()方法根據(jù)Model的類型(這里暫且先這么理解,等看完下個(gè)篇幅就會(huì)知道這里也有可能是Model中的屬性類型)來(lái)生成一個(gè)ICustomTypeDescriptor類型(可以想象成這是對(duì)于一種對(duì)象類型元數(shù)據(jù)描述對(duì)象的抽象定義。讀起來(lái)有點(diǎn)繞口,但是確實(shí)是這么個(gè)意思)。而系統(tǒng)會(huì)有個(gè)默認(rèn)的自定義實(shí)現(xiàn)來(lái)實(shí)現(xiàn)這個(gè)接口類型,我們通過(guò)這個(gè)默認(rèn)的實(shí)現(xiàn)來(lái)獲得Model類型的AttributeList類型。

在有了AttributeList類型后,我們就可以調(diào)用AssociatedMetadataProvider類型的CreateMetadata()方法來(lái)創(chuàng)建Model元數(shù)據(jù)對(duì)象,但是這個(gè)CreateMetadata()的定義是抽象的,而真正的實(shí)現(xiàn)是由繼承了AssociatedMetadataProvider類型的DataAnnotationsModelMetadataProvider類型,由此過(guò)后我們生成得到ModelMetadata元數(shù)據(jù)對(duì)象(真正的過(guò)程比較繁瑣,不然也不會(huì)另起一篇專門用來(lái)講解生成的過(guò)程),得到了Model元數(shù)據(jù)對(duì)象過(guò)后并沒(méi)有結(jié)束,而是繼續(xù)調(diào)用了AssociatedMetadataProvider類型的ApplyMetadataAwareAttributes()方法,并在此方法中,系統(tǒng)框架會(huì)調(diào)用我們自定義實(shí)現(xiàn)了IMetadataAware接口類型的對(duì)象,來(lái)對(duì)Model元數(shù)據(jù)對(duì)象進(jìn)行個(gè)性化修改,并且最后才會(huì)真正的返回Model元數(shù)據(jù)對(duì)象。

有可能看到這里有的朋友對(duì)Model元數(shù)據(jù)還是不怎么清楚和了解,朋友們急我也急,如果我分享的這些知識(shí)大家看完都不知所云那我又是何必呢。先不要急看了多少就是多少在看完這個(gè)Model元數(shù)據(jù)系列的文章后應(yīng)該會(huì)有所了解,將在后續(xù)的篇章中慢慢的揭開(kāi)它的秘密。謝謝大家的支持。




向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI