真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

ASP.NETWebAPIModel-ModelMetadata-創(chuàng)新互聯(lián)

ASP.NET Web API Model-ModelMetadata

成都創(chuàng)新互聯(lián)公司主營通州網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app開發(fā)定制,通州h5成都微信小程序搭建,通州網(wǎng)站營銷推廣歡迎通州等地區(qū)企業(yè)咨詢

前言

前面的幾個(gè)篇幅主要圍繞控制器的執(zhí)行過程,奈何執(zhí)行過程中包含的知識點(diǎn)太龐大了,只能一部分一部分的去講解,在上兩篇中我們看到在控制器方法選擇器根據(jù)請求選定了控制器方法后會生成對應(yīng)的描述對象之后進(jìn)入過濾器執(zhí)行過程中,之后也是我們所講的在授權(quán)過濾器執(zhí)行之后會執(zhí)行對Model的系列操作,中間包括Model元數(shù)據(jù)解析、Model綁定、Model驗(yàn)證,最后會通過Web API框架的獨(dú)有的方式也就是ParameterBinding參數(shù)綁定來執(zhí)行,在這些操作完畢之后會開始執(zhí)行行為過濾器,可在控制器方法執(zhí)行前后進(jìn)行攔截,從技術(shù)方向來說這是AOP思想的一種實(shí)現(xiàn),從業(yè)務(wù)邏輯上來講也是一種依賴注入,扯遠(yuǎn)了,本篇就來談?wù)勗贏SP.NET Web API框架中的Model元數(shù)據(jù),也就是ModelMetadata.

Model-ModelMetadata(對象介紹、基礎(chǔ)知識篇)

在講解Model綁定之前我還是先來講解一下在Web API中的Model元數(shù)據(jù),在我前面的ASP.NET MVC隨筆系列匯總中對MVC框架中的Model的元數(shù)據(jù)有過講解,對MVC有了解的朋友可以去看看,在ASP.NET Web API框架中的Model元數(shù)據(jù)的設(shè)計(jì)思想和MVC框架中的是一樣的,都是對Model進(jìn)行類型解析,然后已樹形結(jié)構(gòu)呈現(xiàn)或者是給需要它的地方使用。為什么說是樹形結(jié)構(gòu)呢?我們來看一下示例,后面再結(jié)合對象類型這么一講解大家就差不多該明白了。

我們先不管在框架中是怎么表示的,先來看一下定義的Model:

示例代碼1-1

publicclassEmployeesInfo
   {
        [Display(Description="員工姓名")]
        publicstringName { get; set; }
 
        [Display(Description="員工年齡")]
        publicintAge { get; set; }
 
        [Display(Description="員工性別")]
        publicstringSex { get; set; }
 
        [Display(Description="員工地址信息")]
        publicAddressAddressInfo { get; set; }
   }
 
   
   publicclassAddress
   {
        [Display(Description="地址信息")]
        publicstringAddressInfo { get; set; }
 
        [Display(Description="郵編")]
        publicstringZipCode { get; set; }
}

在代碼1-1中我定義了一個(gè)Model類型為EmployeesInfo,表示員工的信息,在這其中有幾個(gè)屬性,其中AddressInfo屬性是下面的Address類型,這里是為了說明Model元數(shù)據(jù)所表示的對象存在兩種類型,一種是簡單類型,另一種是復(fù)雜類型。至于這個(gè)類型怎么判斷下面會說,我們還是先來看示例代碼,看下Model經(jīng)過框架生成為Model元數(shù)據(jù)過后包含的信息。

示例代碼1-2

publicclassMetadataController : ApiController
   {
        publicstringGet()
        {
            EmployeesInfoemployeesInfo=newEmployeesInfo()
            {
                Name="JinYuan",
                Age=24,
                Sex="男",
                AddressInfo=newAddress()
                {
                    AddressInfo="南京市",
                    ZipCode="210000"
                }
            };
            ModelMetadatamodelMetadata=this.Configuration.Services.GetModelMetadataProvider().GetMetadataForType(()=>employeesInfo, employeesInfo.GetType());
            StringBuilderstrBuilder=newStringBuilder();
            ModelMetadataAnalysis(strBuilder, modelMetadata);
            returnstrBuilder.ToString();
 
        }
 
        privatevoidModelMetadataAnalysis(StringBuilderstringBuilder, ModelMetadatamodelMetadata)
        {
            if (modelMetadata.IsComplexType==true)
            {
                foreach (varmetadatainmodelMetadata.Properties)
                {
                    ModelMetadataAnalysis(stringBuilder, metadata);
                }
            }
            else
            {
                stringBuilder.AppendLine(modelMetadata.Description).AppendLine("Value:"+modelMetadata.Model);
            }
        }
}

在代碼1-2中,我首先定義了一個(gè)控制器,并且定義了一個(gè)Get()方法,返回類型為string類型,然后在Get()方法中實(shí)例化Model,也就是我們代碼1-1中的定義,在這之后我根據(jù)當(dāng)前控制器基類所包含的HttpConfiguration類型的屬性Configuration,從ServicesContainer 類型的Services屬性中獲取到Model元數(shù)據(jù)提供程序,從而使用這個(gè)提供程序來根據(jù)Model類型生成Model元數(shù)據(jù),這里起初生成好的Model元數(shù)據(jù)也就是modelMetadata變量,它暫時(shí)只是一個(gè)類型的的表示,也就是EmployeesInfo類型,并且其中并不包含EmployeesInfo類型中屬性的元數(shù)據(jù),這里要注意的是不包含只是暫時(shí)的。

然后下面使用了一個(gè)方法ModelMetadataAnalysis(),首先判斷當(dāng)前的Model元數(shù)據(jù)表示的類型是不是復(fù)雜類型,如果是的話就讀取這個(gè)Model元數(shù)據(jù)中的Properties屬性,注意了在讀取的時(shí)候,也就是ModelMetadataAnalysis()方法中的參數(shù)modelMetadata就會開始使用自身的Model元數(shù)據(jù)提供程序來生成自身所表示類型下屬性的Model元數(shù)據(jù)。由此可以看到上面的代碼實(shí)現(xiàn)中只是對簡單類型進(jìn)行了輸出。我們看一下示意圖。

圖1

ASP.NET Web API Model-ModelMetadata

根據(jù)圖1所示的這樣,然后我們再看代碼1-2的實(shí)現(xiàn),最后我們看一下執(zhí)行的結(jié)果。

圖2

ASP.NET Web API Model-ModelMetadata

圖2中所示就是從客戶端和瀏覽器共同訪問返回的結(jié)果值,都是一樣的。

下面我們來講解一下相關(guān)的對象類型。

圖3

ASP.NET Web API Model-ModelMetadata

我們先來看ModelMetadata類型,從圖3中我們可以看到ModelMetadata類型在命名空間System.Web.Http.Metadata下,我們就先來看一下ModelMetadata的定義,

示例代碼1-3

publicclassModelMetadata
   {
        publicModelMetadata(ModelMetadataProviderprovider, TypecontainerType, FuncmodelAccessor, TypemodelType, stringpropertyName);
        publicvirtualDictionaryAdditionalValues { get; }
        publicTypeContainerType { get; }
        publicvirtualboolConvertEmptyStringToNull { get; set; }
        publicvirtualstringDescription { get; set; }
        publicvirtualboolIsComplexType { get; }
        publicboolIsNullableValueType { get; }
        publicvirtualboolIsReadOnly { get; set; }
        publicobjectModel { get; set; }
        publicTypeModelType { get; }
        publicvirtualIEnumerableProperties { get; }
        publicstringPropertyName { get; }
        protectedModelMetadataProviderProvider { get; set; }
        publicstringGetDisplayName();
        publicvirtualIEnumerableGetValidators(IEnumerablevalidatorProviders);
}

代碼1-3中定義了ModelMetadata類型,我們就從構(gòu)造函數(shù)開始講解。

在構(gòu)造函數(shù)中有五個(gè)參數(shù),這些參數(shù)有的是跟屬性對應(yīng)的,就拿第一個(gè)參數(shù)ModelMetadataProvider類型來說,它對應(yīng)的就是ModelMetadata類型中的Provider屬性,有的朋友會問這個(gè)屬性干什么的?還記得上面的示例中講過,在Model元數(shù)據(jù)是復(fù)雜類型的時(shí)候從Properties屬性中獲取當(dāng)前所表示類型下的Model元數(shù)據(jù),就是在獲取的時(shí)候拿什么生成?就是用的這個(gè)Provider屬性對應(yīng)的元數(shù)據(jù)提供程序,這里也講一下Properties屬性,從它的定義中可以看到,是個(gè)IEnumerable類型的屬性,也就是為什么上面我所說的以樹形結(jié)構(gòu)的方式展現(xiàn)給我們看的原因。下面說到構(gòu)造函數(shù)中的第二個(gè)參數(shù)實(shí)例類型,就是這個(gè)元數(shù)據(jù)對象所表示的、所對應(yīng)的類型的容器類型,第三個(gè)參數(shù)比較有意思,是個(gè)Func委托,它是用來獲取當(dāng)前元數(shù)據(jù)對象所表示類型的實(shí)例值,這也就是ModelMetadata類型中Model屬性的屬性值的由來,第四個(gè)參數(shù)就是當(dāng)前元數(shù)據(jù)對應(yīng)的對象類型,也就是對應(yīng)著ModelMetadata類型中ModelType屬性值,最后一個(gè)參數(shù)表示屬性名稱,也對應(yīng)著ModelMetadata類型中的PropertyName屬性值。

下面說說ModelMetadata類型中的其他屬性值,AdditionalValues表示容器屬性,可自行添加任何額外值在其中以鍵值隊(duì)的方式表示,這個(gè)很多框架中設(shè)計(jì)對象時(shí)都會有,可以是object類型,不過這里使用鍵值隊(duì)來表示。

IsComplexType屬性表示當(dāng)前Model元數(shù)據(jù)對象所表示的類型是否是復(fù)雜類型,這個(gè)怎么判斷的呢?

   publicvirtualboolIsComplexType
   {
        get
        {
            return!TypeHelper.HasStringConverter(this.ModelType);
        }
}

就是看類型是否可以轉(zhuǎn)換為String類型。

IsReadOnly屬性下面再講,因?yàn)樵诔跏蓟粋€(gè)Model元數(shù)據(jù)的時(shí)候得到的信息只有這么多,而IsReadOnly屬性則是通過ModelAttribute來控制的。

我們再來看一下ModelMetadataProvider

示例代碼1-4

publicabstractclassModelMetadataProvider
   {
        protectedModelMetadataProvider();
        publicabstractIEnumerableGetMetadataForProperties(objectcontainer, TypecontainerType);
        publicabstractModelMetadataGetMetadataForProperty(FuncmodelAccessor, TypecontainerType, stringpropertyName);
        publicabstractModelMetadataGetMetadataForType(FuncmodelAccessor, TypemodelType);
    }

在代碼1-4中我們看到Model元數(shù)據(jù)提供程序ModelMetadataProvider類型中有三個(gè)抽象方法,本身也是抽象類,這三個(gè)方法的含義來給大家解釋一下。

GetMetadataForProperties()方法是根據(jù)容器實(shí)例、容器的類型來獲取容器中所有屬性的元數(shù)據(jù)類型。

GetMetadataForProperty()方法則是根據(jù)一個(gè)獲取容器實(shí)例的委托、容器類型,和要返回的屬性元數(shù)據(jù)的屬性名稱。

GetMetadataForType()方法就是根據(jù)一個(gè)類型來獲取這個(gè)類型所所表示的元數(shù)據(jù),不過委托參數(shù)是要能獲取到這個(gè)類型的實(shí)例。

下面我們回到代碼1-2中,在我們獲取Model元數(shù)據(jù)提供程序的地方,上面也說過了我們是從哪里獲取到的,現(xiàn)在我們就來看看具體的類型,

示例代碼1-5

this.SetSingle(newDataAnnotationsModelMetadataProvider());

那我們就來看看DataAnnotationsModelMetadataProvider類型中的定義。

示例代碼1-6

publicclassDataAnnotationsModelMetadataProvider : AssociatedMetadataProvider
   {
        publicDataAnnotationsModelMetadataProvider();
 
        protectedoverrideCachedDataAnnotationsModelMetadataCreateMetadataFromPrototype(CachedDataAnnotationsModelMetadataprototype, FuncmodelAccessor);
        protectedoverrideCachedDataAnnotationsModelMetadataCreateMetadataPrototype(IEnumerableattributes, TypecontainerType, TypemodelType, stringpropertyName);
}

我們先不管DataAnnotationsModelMetadataProvider類型,而是看它中定義的函數(shù)的返回類型CachedDataAnnotationsModelMetadata類型。

CachedDataAnnotationsModelMetadata類型

示例代碼1-7

publicclassCachedDataAnnotationsModelMetadata : CachedModelMetadata
   {
        publicCachedDataAnnotationsModelMetadata(CachedDataAnnotationsModelMetadataprototype, FuncmodelAccessor);
        publicCachedDataAnnotationsModelMetadata(DataAnnotationsModelMetadataProviderprovider, TypecontainerType, TypemodelType, stringpropertyName, IEnumerableattributes);
 
        [SecuritySafeCritical]
        protectedoverrideboolComputeConvertEmptyStringToNull();
        [SecuritySafeCritical]
        protectedoverridestringComputeDescription();
        [SecuritySafeCritical]
        protectedoverrideboolComputeIsReadOnly();
}

從代碼1-7中我們可以看到CachedDataAnnotationsModelMetadata類型繼承自CachedModelMetadata類型,也就是CachedModelMetadata類型。

讓我們先來看一下CachedModelMetadata類型

代碼1-8

publicabstractclassCachedModelMetadata : ModelMetadata
   {
        protectedCachedModelMetadata(CachedModelMetadataprototype, FuncmodelAccessor);
        protectedCachedModelMetadata(DataAnnotationsModelMetadataProviderprovider, TypecontainerType, TypemodelType, stringpropertyName, TPrototypeCache prototypeCache);
        publicoverridesealedboolConvertEmptyStringToNull { get; set; }
        publicoverridesealedstringDescription { get; set; }
        publicoverridesealedboolIsComplexType { get; }
        publicoverridesealedboolIsReadOnly { get; set; }
        protected TPrototypeCache PrototypeCache { get; set; }
 
        protectedvirtualboolComputeConvertEmptyStringToNull();
        protectedvirtualstringComputeDescription();
        protectedvirtualboolComputeIsComplexType();
        protectedvirtualboolComputeIsReadOnly();
}

看到這里怎么感覺這么亂的呢亂七八糟的,比較煩躁?。。。?!大家莫慌。

前面說到了Model元數(shù)據(jù)在初始化的時(shí)候便會初始了很多的值,可是大家有沒有想過Model元數(shù)據(jù)的真正的作用?在初始化的時(shí)候可以說我們的Model元數(shù)據(jù)已經(jīng)包含了所表示對象的對象類型和值一些基本的信息,但是我們要給Model上附加額外的動(dòng)作,比如說控制這個(gè)某某屬性是只讀的或者是讓某某屬性換一個(gè)顯示的方式,這種事情是在初始化的時(shí)候Model元數(shù)據(jù)做不了的,那咋整?

看代碼1-8中最下面的Compute開頭的四個(gè)方法,這四個(gè)方法就是用來獲取我們設(shè)置的動(dòng)作然后設(shè)置到Model元數(shù)據(jù)上的,當(dāng)然看了一下實(shí)現(xiàn)并不是我們想要的結(jié)果,而是通過代碼1-7中定義的CachedDataAnnotationsModelMetadata類型來實(shí)現(xiàn)的,在代碼1-7中CachedDataAnnotationsModelMetadata類型繼承的是CachedModelMetadata類型,現(xiàn)在我們就來看看CachedDataAnnotationsMetadataAttributes類型的定義。

CachedDataAnnotationsMetadataAttributes類型

示例代碼1-9

publicclassCachedDataAnnotationsMetadataAttributes
   {
        publicCachedDataAnnotationsMetadataAttributes(IEnumerableattributes);
 
        publicSystem.ComponentModel.DataAnnotations.DisplayAttributeDisplay { get; protectedset; }
        publicSystem.ComponentModel.DataAnnotations.DisplayFormatAttributeDisplayFormat { get; protectedset; }
        publicSystem.ComponentModel.DataAnnotations.EditableAttributeEditable { get; protectedset; }
        publicReadOnlyAttributeReadOnly { get; protectedset; }
    }

代碼1-9中的CachedDataAnnotationsMetadataAttributes類型就是應(yīng)用于元數(shù)據(jù)特性多個(gè)類型的封裝,這里我們暫且不管,知道CachedDataAnnotationsMetadataAttributes類型是個(gè)啥就行了。現(xiàn)在我們回到代碼1-7中看看那幾個(gè)方法的具體實(shí)現(xiàn)方式。

代碼1-10

   [SecuritySafeCritical]
   protectedoverridestringComputeDescription()
   {
        if (base.PrototypeCache.Display==null)
        {
            returnbase.ComputeDescription();
        }
        returnbase.PrototypeCache.Display.GetDescription();
    }

我挑了其中一個(gè),這里可以清楚的看到是要調(diào)用基類當(dāng)中的PrototypeCache屬性,那么這里的PrototypeCache屬性對應(yīng)的是什么類型?

大家可以看一下代碼1-8中PrototypeCache屬性對應(yīng)的是什么類型,是一個(gè)泛型類型,而在CachedDataAnnotationsModelMetadata類型繼承的時(shí)候泛型類型我們可以在代碼1-7中看到,也就是代碼1-9定義的類型。

最后我們看下示意圖。

圖4

ASP.NET Web API Model-ModelMetadata

最后總結(jié)一句在Model元數(shù)據(jù)初始化的時(shí)候便會完成一些初始值的初始化,而對于Model上的行為設(shè)置,則需要通過CachedDataAnnotationsMetadataAttributes類型來執(zhí)行設(shè)置了,而CachedDataAnnotationsMetadataAttributes類型中對應(yīng)的幾個(gè)屬性的類型大家一試便知。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。


本文名稱:ASP.NETWebAPIModel-ModelMetadata-創(chuàng)新互聯(lián)
本文鏈接:http://weahome.cn/article/cdosii.html

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部