中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.NET MVC Model元數據(四)

發布時間:2020-08-11 11:27:03 來源:網絡 閱讀:974 作者:jinyuan0829 欄目:編程語言

ASP.NET MVC Model元數據(四)

前言

前面的篇幅講解了Model元數據生成的過程,并沒有對Model元數據生成過程的內部和Model元數據結構的詳細解釋。看完本篇后將會對Model元數據有更清楚的了解,當然了也不會是特別全面的,因為后面還有篇幅。希望能給大家帶來好的效果。

 

Model元數據

  • 什么是Model元數據?

  • 生成Model元數據的過程【一】

  • 生成Model元數據的過程【二】

  • ModelMetaData的定義、詳解

  • Model元數據應用(常用特性應用)-1

  • Model元數據應用(自定義視圖模板)-2

  • Model元數據應用(IMetadataAware接口使用)-3

 

ModelMetaData的定義、詳解

對于Model元數據的生成可否我們自己來定義呢?回答是肯定的,必須可以阿。MVC框架給我們提供了頂層基類,在調用的時候是從當前上下文中獲取到系統默認實現類(或者是我們自定義的實現類)。我們來看一下示例代碼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類型繼承自DataAnnotationsModelMetadataProvider類型,并且重寫了CreateMetadata()的方法,在CreateMetadata()方法中會根據參數attributes中的特性信息來對Model元數據各種屬性來操作賦值。這個會在下面說到,代碼1-1中并沒有對attributes參數這些來進行解析,而只是實例化了一個Model元數據類型(DataAnnotationsModelMetadata繼承自ModelMetadata)用來返回。這樣定義好了過后系統并不會調用我們自定義的實現,而是需要在項目啟動的時候就添加到系統上下文中,我們就在Global.asax文件中的MvcApplication類型里的Application_Start()方法中來添加示例代碼1-2.

代碼1-2

ModelMetadataProviders.Current = new MyCustomModelMetadataProvider();

這樣定義過后,系統框架在執行的時候就會調用我們的自定義實現了,還可以使用前面篇幅的示例來直接運行,什么結果我沒試過不過肯定是不會有什么特殊效果,真正的目的不在這,而是在CreateMetadata()方法的入口處設上斷點(圖1)然后我們再次按F5執行程序,程序又會執行到我們自定義實現的CreateMetadata()方法。

圖1

ASP.NET MVC Model元數據(四)

按照上面做的意義何在呢?這樣做的意義在于在每次斷點進來的時候,我們可以打開調試的即時窗口,并且輸入CreateMetadata()方法參數的modelType來查看當前所要生成的Model元數據對應的類型或者是屬性,也便于我們自己去更深入的學習。還有一個意思就是證明了我上篇所說的那樣生成的過程。

下面我們來看一下系統默認提供的DataAnnotationsModelMetadataProvider類型中是怎么對Model元數據進行操作的,先看一下默認的實現代碼,

代碼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中,我們看到首先會根據參數attributes轉換為Attribute集合類型的attributeList變量,然后就是在此集合中搜尋第一個DisplayColumnAttribute類型的特性,暫且先不說這個特性類型是干什么的,因為我現在也不太明白。

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

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

從attributeList中獲取第一個EditableAttribute類型的實例,并且根據EditableAttribute類型實例中的AllowEdit屬性值來設置result的IsReadOnly屬性值,代表著指示這個模型是否只讀,EditableAttribute類型指示模型是否可編輯的意思和下面的ReadOnlyAttribute類型很像,只不過同樣是實現只讀效果兩個類型使用中設置的屬性值是相反的。

同樣是從attributeList獲取符合類型條件的第一個DataTypeAttribute類型實例,還有個是DisplayFormatAttribute類型實例,這里會調用默認的提供程序里的另一個函數,在此就不做多的介紹了,我就稍微的說一下就行了。為什么把這兩個放一起呢?因為他們都是對指定的模型輸出格式的設置有關。

ScaffoldColumnAttribute類型實例表示著是否使用基架(模板視圖輔助器的一種,EditorForModel屬于其中之一),當某項屬性上使用了這個特性類的時候,在使用基架的時候會直接跳過這項屬性,在生成的頁面中也不會發現這項屬性。(遭到了嫌棄)

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

最后對于RequiredAttribute類型實例的意思會在Model驗證篇幅中說明。



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

霞浦县| 子洲县| 珲春市| 拉萨市| 武宁县| 临湘市| 商水县| 泰和县| 龙岩市| 彭山县| 威海市| 土默特右旗| 和林格尔县| 沁源县| 九龙坡区| 监利县| 鄂托克前旗| 临海市| 邯郸市| 雅江县| 长宁区| 马龙县| 辽阳县| 佳木斯市| 丰顺县| 灵台县| 鄂温| 新郑市| 攀枝花市| 浮山县| 巨鹿县| 绩溪县| 杨浦区| 黑龙江省| 南宫市| 五大连池市| 英山县| 嘉禾县| 盐源县| 藁城市| 玉田县|