<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ASP.NET MVC的Model元數據提供機制的實現

      在前面的介紹中我們已經提到過表示Model元數據的ModelMetadata對象最終是通過一個名為ModelMetadataProvider的組件提供的,接下來我們著重討論基于ModelMetadataProvider的Model元數據提供機制及其擴展。[本文已經同步到《How ASP.NET MVC Works?》中]

      一、 ModelMetadataProvider

      在ASP.NET MVC的Model元數據相關的應用編程接口中,用于創建Model元數據的ModelMetadataProvider接繼承自抽象類ModelMetadataProvider。如下面的代碼片斷所示,ModelMetadataProvide具有三個抽象方法。GetMetadataForProperties方法用于獲取表示針對指定容器對象和類型所有屬性的Model元數據集合,GetMetadataForProperty獲取針對指定容器對象和類型某個具體屬性對象的Model元數據,而GetMetadataForType則直接返回針對容器對象和類型的Model元數據。

         1: public abstract class ModelMetadataProvider
         2: {    
         3:     public abstract IEnumerable<ModelMetadata> GetMetadataForProperties( object container, Type containerType);
         4:     public abstract ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
         5:     public abstract ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
         6: }

      注:在本文中提及的ModelMetadataProvider在大部分情況泛指直接或者間接繼承自抽象類ModelMetadataProvider,用于提供Model元數據的提供者對象或者類型,請讀者注意區分。

      在ASP.NET MVC的元數據解析系統中使用的ModelMetadataProvider最終通過類型ModelMetadataProviders獲取。如下面的代碼片斷所示,ModelMetadataProviders具有一個ModelMetadataProvider類型的靜態可讀可寫屬性Current用于獲取和設置當前使用的ModelMetadataProvider。

         1: public class ModelMetadataProviders
         2: {
         3:     public static ModelMetadataProvider Current { get; set; }
         4: }

      二、DataAnnotationsModelMetadataProvider

      通過前面的介紹我們知道Model元數據是通過定義在System.ComponentModel.DataAnnotations命名空間下的標注特性來定義的,Model元數據解析系統通過對應用在表示Model的數據類型及其屬性成員的標注特性進行解析從而對創建的Model元數據進行對應的初始化,而這個工作是通過DataAnnotationsModelMetadataProvider來實現的。

      不過DataAnnotationsModelMetadataProvider并沒有直接繼承自ModelMetadataProvider,而是繼承自抽象類AssociatedMetadataProvider,后者是ModelMetadataProvider的子類。AssociatedMetadataProvider的主要作用是對應用在Model類型或屬性上所有“關聯”的特性,這也是它命名的由來。如下面的代碼片斷所示,AssociatedMetadataProvider實現了定義在ModelMetadataProvider的三個方法。

         1: public abstract class AssociatedMetadataProvider : ModelMetadataProvider
         2: {
         3:     protected abstract ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName);
         4:     
         5:     public override IEnumerable<ModelMetadata> GetMetadataForProperties(object container, Type containerType);   
         6:     public override ModelMetadata GetMetadataForProperty(Func<object> modelAccessor, Type containerType, string propertyName);
         7:     public override ModelMetadata GetMetadataForType(Func<object> modelAccessor, Type modelType);
         8: }

      對于AssociatedMetadataProvider實現的三個方法,它并緊緊是通過反射將應用在Model類型和對應屬性上的所有特性,并將這個特性列表作為參數(attributes)傳入抽象方法CreateMetadata完成Model元數據的創建。值得一提的是,當通過調用CreateMetadata創建出ModelMetadata之后,會從特性列表中篩選出實現了IMetadataAware接口的特性,并將該ModelMetadata對象作為參數調用它們的OnMetadataCreated方法。

      繼承自AssociatedMetadataProvider的DataAnnotationsModelMetadataProvider實現了抽象方法,它根據傳入的特性列表以及其他相關的信息(用于創建Model對象的委托、容器和Model類型以及屬性名稱)實現對Model元數據的最終創建。下面的代碼片斷就是整個DataAnnotationsModelMetadataProvider類型的定義。

         1: public class DataAnnotationsModelMetadataProvider : AssociatedMetadataProvider
         2: {    
         3:     public DataAnnotationsModelMetadataProvider();
         4:     protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, 
         5:     Func<object> modelAccessor, Type modelType, string propertyName);
         6: }

      包含在Model元數據提供系統的ModelMetadataProvider、AssociatedMetadataProvider、DataAnnotationsModelMetadataProvider和ModelMetadataProviders與ModelMetadata之間的關系可以通過如下圖所示的UML來體現。

      image

      DataAnnotationsModelMetadataProvider最終實現了基于標注特性的Model元數據的解析,但是在默認情況下使用的ModelMetadataProvider類型卻不是DataAnnotationsModelMetadataProvider,而是CachedDataAnnotationsModelMetadataProvider,它對解析出來的元數據信息進行了相應的環村以提供性能,其實最終實現對Model元數據創建的還是DataAnnotationsModelMetadataProvider。

      三、對Model元數據提供系統的擴展

      對Model元數據提供系統的擴展主要體現在對ModelMetadataProvider自定義上。基于標注特性的元數據定義方式最終是通過DataAnnotationsModelMetadataProvider來實現,通過自定義ModelMetadataProvider我們完全可以提供一種全新的Model元數據定義方式。不過我們經常使用的方式還是通過繼承DataAnnotationsModelMetadataProvider在現有的元數據提供機制上做一些擴展。

      在《一個重要的接口:IMetadataAware》中我們創建了一個用于控制目標元素顯示名稱的DisplayTextAttribute特性。該特性支持基于資源文件的本地化,并且可以省去對資源條目名稱和資源類型的顯式指定。該DisplayTextAttribute特性是通過實現IMetadataAware接口的形式實現的,現在我們將它轉換成基于自定義ModelMetadataProvider的實現方式。對于之前定義的DisplayTextAttribute特性,我們只需要對其進行簡單的修改。如下面的代碼片斷所示,我們刪除了它實現的IMetadataAware接口,將實現的OnMetadataCreated方法名改成SetMetadata。
         1: [AttributeUsage(AttributeTargets.Class| AttributeTargets.Property)]
         2: public class DisplayTextAttribute: Attribute
         3: {
         4:     private static Type staticResourceType;
         5:     public string DisplayName { get; set; }
         6:     public Type ResourceType { get; set; }
         7:  
         8:     public DisplayTextAttribute()
         9:     {
        10:         this.ResourceType = staticResourceType;
        11:     }
        12:  
        13:     public void SetMetadata(ModelMetadata metadata)
        14:     {
        15:         this.DisplayName = this.DisplayName ?? (metadata.PropertyName ?? metadata.ModelType.Name);
        16:         if (null == this.ResourceType)
        17:         {
        18:             metadata.DisplayName = this.DisplayName;
        19:             return;
        20:         }
        21:         PropertyInfo property = this.ResourceType.GetProperty(this.DisplayName, BindingFlags.NonPublic|BindingFlags.Public| BindingFlags.Static);
        22:         metadata.DisplayName = property.GetValue(null, null).ToString();
        23:     }
        24:  
        25:     public static void SetResourceType(Type resourceType)
        26:     {
        27:         staticResourceType = resourceType;
        28:     }
        29: }

      為了將DisplayTextAttribute應用到Model元數據的初始化過程中,我們通過繼承DataAnnotationsModelMetadataProvider創建了如下一個ExtendedDataAnnotationsProvider。在重寫的CreateMetadata方法中,我們先調用基類的同名方法得到一個ModelMetadata對象。如果該對象的DisplayName屬性為空,在從特性列表中獲取DisplayTextAttribute特性并調用其SetDisplayName方法對ModelMetadata的DisplayName屬性進行設置。

         1: public class ExtendedDataAnnotationsProvider : DataAnnotationsModelMetadataProvider 
         2: {
         3:     protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType,  Func<object> modelAccessor, Type modelType, string propertyName)
         4:     {
         5:         ModelMetadata metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
         6:         if(string.IsNullOrEmpty(metadata.DisplayName))
         7:         {
         8:             DisplayTextAttribute displayTextAttribute =  attributes.OfType<DisplayTextAttribute>().FirstOrDefault();
         9:             if (null != displayTextAttribute)
        10:             {
        11:                 displayTextAttribute.SetDisplayName(metadata);
        12:             }
        13:         }
        14:         return metadata;
        15:     }
        16: }

      對于之前創建的演示實例,如果我們在Global.asax中通過如下的方式對我們自定義的ExtendedDataAnnotationsProvider進行注冊,該實例應用同樣可以正常運行。

         1: public class MvcApplication : System.Web.HttpApplication
         2: {
         3:     //其他成員
         4:     protected void Application_Start()
         5:     {
         6:         //其他操作
         7:         DisplayTextAttribute.SetResourceType(typeof(Resources));
         8:         ModelMetadataProviders.Current = new ExtendedDataAnnotationsProvider();
         9:     }
        10: }

      這個實例直接使用了擴展的DataAnnotationsModelMetadataProvider替換了默認的CachedDataAnnotationsModelMetadataProvider,意味著失去了對成功解析出來的元數據的緩存功能,會對性能造成一定的影響。但是由于CachedDataAnnotationsModelMetadataProvider已經將CreateMetadata方法封閉(Seal),又不能直接繼承CachedDataAnnotationsModelMetadataProvider。如果項目里面確實需要使用到類似的用法,可以考慮自己實現緩存。

      posted @ 2012-05-09 07:52  Artech  閱讀(8197)  評論(10)    收藏  舉報
      主站蜘蛛池模板: 色综合色国产热无码一| 国产亚洲精品VA片在线播放 | 少妇激情一区二区三区视频小说 | 精品国偷自产在线视频99| 国产亚洲精品岁国产精品| 精品自拍自产一区二区三区| 国产精品人成视频免费国产| 国产欧美日韩高清在线不卡| 精品粉嫩国产一区二区三区| 国产亚洲欧美精品久久久| 最新国产精品拍自在线观看| 色五开心五月五月深深爱| 平湖市| 综合色一色综合久久网| 亚洲国产午夜精品福利| √天堂中文www官网在线| 国产男女猛烈无遮挡免费视频网站| 伦理片午夜视频在线观看| 久久中文字幕国产精品| 国产成人精品午夜福利在线观看| 亚洲中文字幕在线二页| 亚洲欧美人成电影在线观看 | 在线看国产精品自拍内射| 亚洲日韩在线中文字幕第一页| 国产精品亚洲аv无码播放| 国精品无码人妻一区二区三区| 国产高清亚洲一区亚洲二区| 国产高清一区二区不卡| 日日躁狠狠躁狠狠爱| 中文字幕有码无码人妻在线| 欧美日本激情| 亚洲丰满老熟女激情av| 亚洲欧美高清在线精品一区二区| 中文字幕国产原创国产| 亚洲成熟女人av在线观看| 国产午夜亚洲精品久久| 亚洲精品国产av成拍色拍个 | 亚洲成人四虎在线播放| 亚洲中文无码手机永久| 伊人激情一区二区三区av| 人妻互换一二三区激情视频|