ASP.NET MVC Model中繼資料及其定製: Model中繼資料的定製

來源:互聯網
上載者:User

在《上篇》我們已經提到過了,Model中繼資料的定製是通過在作為Model的資料類型極其屬性成員上應用相應的特性來實現,這些用於聲明式中繼資料定義的特性大都定義在System.ComponentModel.DataAnnotations.dll程式集中,程式集的名稱同時也是對應的命名空間名稱,所以我們可以它們為資料註解特性(Data Annotation Attribute),接下來我們來介紹一些常用的資料註解特性,以及它們對於中繼資料具有怎樣的影響。

一、UIHintAttribute

HtmlHelper和HtmlHelper<TModel>定義了一系列的基於Model的模板方法,比如Display/DisplayFor、Editor/EditorFor、DisplayForModel/EditForModel、Lable/LabelFor和DisplayText/DisplayTextFor。所謂模板方法,就是說我們在通過調用這些方法將代表Model的資料呈現在View中的時候,並不對最終呈現的UI元素進行顯失地控制,而採用預設或者指定的模板來決定最終呈現在瀏覽器中的HTML。每個具體的模板均具有相應的名稱,這些模板方法在進行Model呈現的時候根據對應的Model中繼資料得到對應的模板名稱。具體來說,模板的名稱通過ModelMetadata的TemplateHint屬性工作表示,如下面的代碼片斷所示,這是一個字串類型的可讀寫屬性。

   1: public class ModelMetadata
2: {
3: //其他成員
4: public virtual string TemplateHint{get;set;}
5: }

ModelMetadata的TemplateHint屬性可以通過UIHintAttribute特性來定製。如下面的代碼片斷所示,UIHintAttribute具有PresentationLayer和UIHint兩個唯讀屬性,分別用於限制展現層的類型(比如“HTML”、“Silverlight”、“WPF”、“WinForms”等和模板名稱,這兩個屬性均在建構函式中初始化。

   1: [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple=true)]
2: public class UIHintAttribute : Attribute
3: {
4: //其他成員
5: public UIHintAttribute(string uiHint);
6: public UIHintAttribute(string uiHint, string presentationLayer);
7:
8: public string PresentationLayer { get; }
9: public string UIHint { get; }
10: }

通過應用在UIHintAttribute上的AttributeUsageAttribute定義我們不難看出,由於其AllowMultiple屬性被設定為True,意味著我們可以在相同的目標元素上應用多個UIHintAttribute特性,那麼哪一個會被選擇用於定製Model中繼資料呢?

如果多個UIHintAttribute應用到了相應的元素(類型或者屬性),會先選擇一個PresentationLayer屬性為“MVC”(不區分大小寫)的UIHintAttribute。如果這樣的UIHintAttribute不存在,則選擇一個PresentationLayer屬性值為空白的UIHintAttribute。值得一提的是,如果具有多個匹配的UIHintAttribute可控選擇,系統會選擇第一個,但是通過反射擷取到的Attribute的順序和Attribute被標註的屬性沒有直接的關係。

接下來我們通過一個簡單的執行個體來示範UIHintAttribute特性對Model中繼資料的影響,以及對應用在相同目標元素上的多個UIHintAttribute的選擇策略。考慮到重用性,我們編寫了如下一個靜態輔助方法GetModelMetadata<TModel>用於擷取Model類型為TModel針對指定屬性的Model中繼資料。

   1: public static ModelMetadata GetModelMetadata<TModel>(string propertyName)
2: {
3: ModelMetadataProvider provider = ModelMetadataProviders.Current;
4: ModelMetadata containerMetadata = new ModelMetadata(provider, null, () => null, typeof(TModel), null);
5: return containerMetadata.Properties.FirstOrDefault(m => m.PropertyName == propertyName);
6: }

我們通過如下的代碼定義了一個類型為Model的資料類型,三個屬性Foo、Bar和Baz定義其中。對於屬性Bar來說,我們同時應用了兩個模板名稱分別為“Template A”和“Template B”的UIHintAttribute特性,後者將字元“Mvc”作為presentationLayer參數的值。屬性Baz跨平台 app了基於模板名稱“Template A”的UIHintAttribute特性。

   1: public class Model
2: {
3: public string Foo { get; set; }
4:
5: [UIHint("Template A")]
6: [UIHint("Template B", "Mvc")]
7: public string Bar { get; set; }
8:
9: [UIHint("Template A")]
10: public string Baz { get; set; }
11: }

現在我們在一個控制台程式中編寫如下的測試程式。我們通過上面定義的輔助方法GetModelMetadata<TModel>建立針對定義在資料類型Model中的Foo、Bar和Baz三個屬性的ModelMetadata,並分別列印出對應的TemplateHint屬性。

   1: ModelMetadata foo = GetModelMetadata<Model>("Foo");
2: ModelMetadata bar = GetModelMetadata<Model>("Bar");
3: ModelMetadata baz = GetModelMetadata<Model>("Baz");
4:
5: Console.WriteLine("Foo: {0}", foo.TemplateHint??"N/A");
6: Console.WriteLine("Bar: {0}", bar.TemplateHint ?? "N/A");
7: Console.WriteLine("Baz: {0}", baz.TemplateHint ?? "N/A");

上面的測試程式執行之後會在控制台上產生如下的輸出結果,這和我們上面介紹的關於UIHintAttribute特性針對Model中繼資料的定製,以及針對應用在相同目標元素上的多個UIHintAttribute特性的選擇策略是相符的。

   1: Foo: N/A
2: Bar: Template B
3: Baz: Template A

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.