ASP.NETMVCModel元數(shù)據(jù)(四)-創(chuàng)新互聯(lián)

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

前言

前面的篇幅講解了Model元數(shù)據(jù)生成的過(guò)程,并沒(méi)有對(duì)Model元數(shù)據(jù)生成過(guò)程的內(nèi)部和Model元數(shù)據(jù)結(jié)構(gòu)的詳細(xì)解釋??赐瓯酒髮?huì)對(duì)Model元數(shù)據(jù)有更清楚的了解,當(dāng)然了也不會(huì)是特別全面的,因?yàn)楹竺孢€有篇幅。希望能給大家?guī)?lái)好的效果。

成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的裕華網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

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

ModelMetaData的定義、詳解

對(duì)于Model元數(shù)據(jù)的生成可否我們自己來(lái)定義呢?回答是肯定的,必須可以阿。MVC框架給我們提供了頂層基類(lèi),在調(diào)用的時(shí)候是從當(dāng)前上下文中獲取到系統(tǒng)默認(rèn)實(shí)現(xiàn)類(lèi)(或者是我們自定義的實(shí)現(xiàn)類(lèi))。我們來(lái)看一下示例代碼1-1.

代碼1-1

 public class MyCustomModelMetadataProvider:DataAnnotationsModelMetadataProvider
    {
        protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
        {
            DataAnnotationsModelMetadata result = new DataAnnotationsModelMetadata(this, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute);

            return result;
        }
    }

代碼1-1中的MyCustomModelMetadataProvider類(lèi)型繼承自DataAnnotationsModelMetadataProvider類(lèi)型,并且重寫(xiě)了CreateMetadata()的方法,在CreateMetadata()方法中會(huì)根據(jù)參數(shù)attributes中的特性信息來(lái)對(duì)Model元數(shù)據(jù)各種屬性來(lái)操作賦值。這個(gè)會(huì)在下面說(shuō)到,代碼1-1中并沒(méi)有對(duì)attributes參數(shù)這些來(lái)進(jìn)行解析,而只是實(shí)例化了一個(gè)Model元數(shù)據(jù)類(lèi)型(DataAnnotationsModelMetadata繼承自ModelMetadata)用來(lái)返回。這樣定義好了過(guò)后系統(tǒng)并不會(huì)調(diào)用我們自定義的實(shí)現(xiàn),而是需要在項(xiàng)目啟動(dòng)的時(shí)候就添加到系統(tǒng)上下文中,我們就在Global.asax文件中的MvcApplication類(lèi)型里的Application_Start()方法中來(lái)添加示例代碼1-2.

代碼1-2

ModelMetadataProviders.Current = new MyCustomModelMetadataProvider();

這樣定義過(guò)后,系統(tǒng)框架在執(zhí)行的時(shí)候就會(huì)調(diào)用我們的自定義實(shí)現(xiàn)了,還可以使用前面篇幅的示例來(lái)直接運(yùn)行,什么結(jié)果我沒(méi)試過(guò)不過(guò)肯定是不會(huì)有什么特殊效果,真正的目的不在這,而是在CreateMetadata()方法的入口處設(shè)上斷點(diǎn)(圖1)然后我們?cè)俅伟碏5執(zhí)行程序,程序又會(huì)執(zhí)行到我們自定義實(shí)現(xiàn)的CreateMetadata()方法。

圖1

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

按照上面做的意義何在呢?這樣做的意義在于在每次斷點(diǎn)進(jìn)來(lái)的時(shí)候,我們可以打開(kāi)調(diào)試的即時(shí)窗口,并且輸入CreateMetadata()方法參數(shù)的modelType來(lái)查看當(dāng)前所要生成的Model元數(shù)據(jù)對(duì)應(yīng)的類(lèi)型或者是屬性,也便于我們自己去更深入的學(xué)習(xí)。還有一個(gè)意思就是證明了我上篇所說(shuō)的那樣生成的過(guò)程。

下面我們來(lái)看一下系統(tǒng)默認(rèn)提供的DataAnnotationsModelMetadataProvider類(lèi)型中是怎么對(duì)Model元數(shù)據(jù)進(jìn)行操作的,先看一下默認(rèn)的實(shí)現(xiàn)代碼,

代碼1-3

protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
        {
            List<Attribute> attributeList = new List<Attribute>(attributes);
            DisplayColumnAttribute displayColumnAttribute = attributeList.OfType<DisplayColumnAttribute>().FirstOrDefault();
            DataAnnotationsModelMetadata result = new DataAnnotationsModelMetadata(this, containerType, modelAccessor, modelType, propertyName, displayColumnAttribute);
            
            // Do [HiddenInput] before [UIHint], so you can override the template hint
            HiddenInputAttribute hiddenInputAttribute = attributeList.OfType<HiddenInputAttribute>().FirstOrDefault();
            if (hiddenInputAttribute != null)
            {
                result.TemplateHint = "HiddenInput";
                result.HideSurroundingHtml = !hiddenInputAttribute.DisplayValue;
            }

            // We prefer [UIHint("...", PresentationLayer = "MVC")] but will fall back to [UIHint("...")]
            IEnumerable<UIHintAttribute> uiHintAttributes = attributeList.OfType<UIHintAttribute>();
            UIHintAttribute uiHintAttribute = uiHintAttributes.FirstOrDefault(a => String.Equals(a.PresentationLayer, "MVC", StringComparison.OrdinalIgnoreCase))
                                              ?? uiHintAttributes.FirstOrDefault(a => String.IsNullOrEmpty(a.PresentationLayer));
            if (uiHintAttribute != null)
            {
                result.TemplateHint = uiHintAttribute.UIHint;
            }

            EditableAttribute editable = attributes.OfType<EditableAttribute>().FirstOrDefault();
            if (editable != null)
            {
                result.IsReadOnly = !editable.AllowEdit;
            }
            else
            {
                ReadOnlyAttribute readOnlyAttribute = attributeList.OfType<ReadOnlyAttribute>().FirstOrDefault();
                if (readOnlyAttribute != null)
                {
                    result.IsReadOnly = readOnlyAttribute.IsReadOnly;
                }
            }

            DataTypeAttribute dataTypeAttribute = attributeList.OfType<DataTypeAttribute>().FirstOrDefault();
            DisplayFormatAttribute displayFormatAttribute = attributeList.OfType<DisplayFormatAttribute>().FirstOrDefault();
           // SetFromDataTypeAndDisplayAttributes(result, dataTypeAttribute, displayFormatAttribute);

            ScaffoldColumnAttribute scaffoldColumnAttribute = attributeList.OfType<ScaffoldColumnAttribute>().FirstOrDefault();
            if (scaffoldColumnAttribute != null)
            {
                result.ShowForDisplay = result.ShowForEdit = scaffoldColumnAttribute.Scaffold;
            }

            DisplayAttribute display = attributes.OfType<DisplayAttribute>().FirstOrDefault();
            string name = null;
            if (display != null)
            {
                result.Description = display.GetDescription();
                result.ShortDisplayName = display.GetShortName();
                result.Watermark = display.GetPrompt();
                result.Order = display.GetOrder() ?? ModelMetadata.DefaultOrder;

                name = display.GetName();
            }

            if (name != null)
            {
                result.DisplayName = name;
            }
            else
            {
                DisplayNameAttribute displayNameAttribute = attributeList.OfType<DisplayNameAttribute>().FirstOrDefault();
                if (displayNameAttribute != null)
                {
                    result.DisplayName = displayNameAttribute.DisplayName;
                }
            }

            RequiredAttribute requiredAttribute = attributeList.OfType<RequiredAttribute>().FirstOrDefault();
            if (requiredAttribute != null)
            {
                result.IsRequired = true;
            }

            return result;
        }

在代碼1-3中,我們看到首先會(huì)根據(jù)參數(shù)attributes轉(zhuǎn)換為Attribute集合類(lèi)型的attributeList變量,然后就是在此集合中搜尋第一個(gè)DisplayColumnAttribute類(lèi)型的特性,暫且先不說(shuō)這個(gè)特性類(lèi)型是干什么的,因?yàn)槲椰F(xiàn)在也不太明白。

然后就是根據(jù)CreateMetadata()方法中的參數(shù)實(shí)例化一個(gè)DataAnnotationsModelMetadata類(lèi)型的元數(shù)據(jù),這個(gè)類(lèi)型上面說(shuō)過(guò)了。繼續(xù)往下看,然后就到了從attributeList變量獲取第一個(gè)HiddenInputAttribute類(lèi)型的特性實(shí)例,在判斷不為空后,對(duì)Model元數(shù)據(jù)DataAnnotationsModelMetadata類(lèi)型變量result的兩個(gè)屬性開(kāi)始賦值(下文中對(duì)Model元數(shù)據(jù)DataAnnotationsModelMetadata類(lèi)型變量result統(tǒng)稱(chēng)叫result),首先第一個(gè)是Model元數(shù)據(jù)的TemplateHint屬性,這個(gè)屬性表示著這個(gè)Model元數(shù)據(jù)所表示的對(duì)象要使用哪個(gè)視圖模板來(lái)生成Html代碼(視圖模板的內(nèi)容這個(gè)系列的后面篇幅會(huì)有講解,到時(shí)候再回頭來(lái)看一下,學(xué)習(xí)嘛感覺(jué)就是一個(gè)迭代的過(guò)程)。然后是HideSurroundingHtml屬性的賦值,對(duì)應(yīng)的是HiddenInputAttribute類(lèi)型的DisplayValue值,HiddenInputAttribute類(lèi)型表示的是是否將屬性或者字段值顯示為隱藏的Input元素,如果我們這樣寫(xiě)的話[HiddenInput(DisplayValue = false)],HideSurroundingHtml屬性值則為true,代表的意思就是使用關(guān)聯(lián)的Html元素來(lái)呈現(xiàn)對(duì)象模型,意思就是用HiddenInputAttribute類(lèi)型所關(guān)聯(lián)隱藏輸入域來(lái)呈現(xiàn)我們所指定的屬性或者字段。這里可能有點(diǎn)繞,不過(guò)不妨礙,下個(gè)篇幅會(huì)講示例用的效果。

切回主題繼續(xù)講,下面則是從attributeList中獲取UIHintAttribute類(lèi)型的集合,并且經(jīng)過(guò)一番判斷獲取一個(gè)UIHintAttribute類(lèi)型的實(shí)例,并且還是賦值到TemplateHint屬性(上面說(shuō)過(guò)),這里就覆蓋掉了,在我們使用默認(rèn)的Model元數(shù)據(jù)提供程序的時(shí)候就要注意這些了,再繼續(xù)往下看。

從attributeList中獲取第一個(gè)EditableAttribute類(lèi)型的實(shí)例,并且根據(jù)EditableAttribute類(lèi)型實(shí)例中的AllowEdit屬性值來(lái)設(shè)置result的IsReadOnly屬性值,代表著指示這個(gè)模型是否只讀,EditableAttribute類(lèi)型指示模型是否可編輯的意思和下面的ReadOnlyAttribute類(lèi)型很像,只不過(guò)同樣是實(shí)現(xiàn)只讀效果兩個(gè)類(lèi)型使用中設(shè)置的屬性值是相反的。

同樣是從attributeList獲取符合類(lèi)型條件的第一個(gè)DataTypeAttribute類(lèi)型實(shí)例,還有個(gè)是DisplayFormatAttribute類(lèi)型實(shí)例,這里會(huì)調(diào)用默認(rèn)的提供程序里的另一個(gè)函數(shù),在此就不做多的介紹了,我就稍微的說(shuō)一下就行了。為什么把這兩個(gè)放一起呢?因?yàn)樗麄兌际菍?duì)指定的模型輸出格式的設(shè)置有關(guān)。

ScaffoldColumnAttribute類(lèi)型實(shí)例表示著是否使用基架(模板視圖輔助器的一種,EditorForModel屬于其中之一),當(dāng)某項(xiàng)屬性上使用了這個(gè)特性類(lèi)的時(shí)候,在使用基架的時(shí)候會(huì)直接跳過(guò)這項(xiàng)屬性,在生成的頁(yè)面中也不會(huì)發(fā)現(xiàn)這項(xiàng)屬性。(遭到了嫌棄)

同樣的DisplayAttribute類(lèi)型的實(shí)例也是從attributeList獲取符合類(lèi)型條件的第一個(gè),DisplayAttribute類(lèi)型實(shí)例里有個(gè)Name屬性會(huì)被設(shè)置到result的DisplayName屬性,這個(gè)屬性的意思就是指定的模型顯示到頁(yè)面的值。而DisplayNameAttribute類(lèi)型實(shí)例的意思和DisplayAttribute類(lèi)型的相近,只不過(guò)DisplayNameAttribute類(lèi)型可以用于類(lèi)類(lèi)型,轉(zhuǎn)定義我們一看便知。

最后對(duì)于RequiredAttribute類(lèi)型實(shí)例的意思會(huì)在Model驗(yàn)證篇幅中說(shuō)明。

創(chuàng)新互聯(lián)www.cdcxhl.cn,專(zhuān)業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開(kāi)啟,新人活動(dòng)云服務(wù)器買(mǎi)多久送多久。

網(wǎng)頁(yè)標(biāo)題:ASP.NETMVCModel元數(shù)據(jù)(四)-創(chuàng)新互聯(lián)
當(dāng)前地址:http://muchs.cn/article38/ddhesp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供虛擬主機(jī)Google、用戶體驗(yàn)網(wǎng)站收錄、品牌網(wǎng)站建設(shè)、品牌網(wǎng)站設(shè)計(jì)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)