ASP.NET MVC Model中繼資料(四)

來源:互聯網
上載者:User

標籤:asp.net mvc metadata   asp.net mvc   .net   c#   mvc   

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

按照上面做的意義何在呢?這樣做的意義在於在每次斷點進來的時候,我們可以開啟調試的即時視窗,並且輸入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驗證篇幅中說明。



金源

出處:http://blog.csdn.net/jinyuan0829

本文著作權歸作者和CSDN共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.