asp.net Model元数据学习一

1.Model元数据

   Model元数据是对数据类型的描述,它为参数绑定、参数验证、数据对象在View上的呈现提供相应的指导信息。

   Model元数据是一种分层次的结构,比如一个数据对象有4个属性,其中一个属性又是一个数据对象,这个数据对象也有自己的属性。ASP.NET MVC用于描述Model元数据的是一个ModelMetadata对象,其代码片段如下。他的只读属性Properties表示描述所有属性成员的Model元数据列表。

 public class ModelMetadata
        {
            //其他成员...

            //4个与类型相关只读属性
            //这个属性表示Model自身的数据类型
            public Type ModelType { get; }
            //看名字是容器类型,因此这个属性表示此Model的父Model,对于本来就是父节点的ModelType,其值为null
            public Type ContainerType { get; }
            //判断ModelType是不是一个复杂类型
            public virtual bool IsComplexType { get; }
            //判断ModelType是不是一个可为空类型
            public bool IsNullableValueType { get; }

            //这个属性有2种赋值:这个数据类型具体的数据对象或者这个属性的属性值
            public object Model { get; set; }
            //表示对应的属性名,如果是具体数据对象则PropertyName为null
            public string PropertyName { get; }
            //用于存储一些自定义的属性,字典元素的Key代表自定义属性的名称,Value代表值。我们可以在数据类型或者其数据
            //成员上应用AdditionalMetadataAttribute特性为对应的ModelMetadata对象添加自定义属性。
            public virtual Dictionary<string, object> AdditionalValues { get; }
            //从类型命名可以看到它是一个ModelMetadata对象提供者
            protected ModelMetadataProvider Provider { get; set; } 
        }

   描述数据类型本身的ModelMetadata和描述这个数据类型属性的ModelMetadata是一种包含关系,一般将前者称为后者的容器。ModelMetadata对象的作用就是对某个类型或其属性成员的描述。IsComplexType属性用来判断被描述的数据类型是简单类型还是复杂类型,判断的标准只有一个:是否支持源自字符串的类型转化。

2.Model元数据的定制

   ASP.NET利用数据注解特性来定制地描述目标类型或者数据成员的Model元数据,这些注解特性基本上定义在System.ComponentModel.DataAnnotations.dll程序集里面。Model元数据决定了对应数据对象在View的默认呈现方式。接下来学习6个重要的数据特性。

   (1)UIHintAttribute

       HtmlHelper和HtmlHelper<TModel>定义了一系列模板方法,比如Display/DisplayFor、Edit/EditFor、DisplayForModel/EditForModel、Label/LabelFor等。所谓模板方法,意味着我们在调用这些模板方法时,数据将会按照定义的模板来最终呈现在浏览器上。每个模板均具有一个确定的名称,如果在调用这些模板方法的时候没有显示指定采用什么模板,此时则会利用描述被呈现数据的Model元数据得到默认采用的模板。默认采用的模板名称通过ModelMetadata的TemplateHint属性表示:

public virtual string TemplateHint{get;set;}。TemplateHint属性可以通过UIHintAttribute特性来定制,UIHintAttribute有2个重要的属性:string类型的PresentationLayer表示展现层的类型(比如Html,WPF,WinForms等);string类型的UIHint描述采用的模板名称。对于应用在UIHintAttribute类型上的AttributeUsageAttribute特性来说,其AllowMultiple属性被设置为true,意味着我们可以在相同的目标元素上应用多个UIHintAttribute特性。当遇到上述情况时,ASP.NET MVC会优先选择PresentationLayer为MVC的那一个(不区分大小写),如果不存在PresentationLayer属性值为MVC,则会选择PresentationLayer为null的UIHintAttribute特性,如果具有多个匹配成功的则选择第一个。

   (2)HiddenlnputAttribute与ScaffoldColumnAttribute

       顾名思义,第一个特性是用来对Model的某个属性实现隐藏的效果,还有HiddenlnputAttribute并没有定义在DataAnnotations.dll这个定义了大多数特性的程序集里面,而是定义在System.Web.Mvc这个命名空间下,因此这个特性是转为MVC设计的。在默认情况下,应用了HiddenlnputAttribute这个特性的目标对象依然会呈现在View中,但是无法编辑。如果想让目标隐藏,可以再加特性时将DisplayValue属性设置为False(默认是True)。比如现在有一个变量test如下:

   [HiddenInput]或者[HiddenInput(DisplayValue=false)]

   public string test{get;set;}

   HiddenInputAttribute特性针对Model元数据的定制体现在ModelMetadata的2个属性上:一个是代表默认模板的TemplateHint属性;一个是bool类型的HideSurroundingHtml,它表示目标元素是否需要显示在界面上;效果体现如下:当目标类型或者数据成员的ModelMetadata对象上加了HiddenInputAttribute特性时,这个对象的TemplateHint属性设置为“HiddenInput”,HideSurroundingHtml的值则由DisplayValue来决定。当有多个特性同时定制ModelMetadata时,会有一个优先级,具体的要看手册,这里当UIHintAttribute和HiddenInputAttribute同时作用时前者的优先级更高。

   ScaffoldColumnAttribute功能与Hidden特性差不多,区别在于:Hidden特性是在html代码里加上hidden标签,而Scaffold则是让html根本就不出现这个属性。ScaffoldColumnAttribute有一个只读属性Scaffold表示目标元素是否出现在生成的html中,该属性在构造函数中初始化,它最终用于控制ModelMetadata的ShowForDisplay和ShowForEdit属性。上面2个属性分别表示是否出现在Html和是否出现在编辑模式下的html,这两个属性在默认情况下均为True。

   (3)DataTypeAttribute与DisplayFormatAttribute

       DataTypeAttribute特性是经常使用的用于指定数据类型的数据标注特性,这里的数据类型不是int或string这样的CLR类型,而是通过DataType枚举表示的具有某种格式的数据类型,比如时间、日期、电话号码等特殊的格式类型。此特性继承自ValidationAttribute类,因此它实际是一个验证特性。DataTypeAttribute的只读属性涉及另外一个与数据格式化相关的特性,来看下定义:

public  DisplayFormatAttribute DisplayFormat{get;},对于DisplayFormatAttribute我们可以利用它指定一个格式化字符串以控制目标元素在界面上的显示格式。这个格式化字符串是通过DisplayFormatAttribute类里面的DataFormatString来表示的。当我们针对某个具体的DataType枚举对象创建一个DataTypeAttribute对象的时候,它会根据对应的格式化字符串去创建DisplayFormatAttribute对象,也就是为DisplayFormat赋值。在这里直接应用的DisplayFormatAttribute比DataTypeAttribute携带的DisplayFormat具有更高的优先级。

   (4)EditableAttribute与ReadOlnyAttribute

       上面这两个特性用于控制目标数据元素的可读/写性,它们分别拥有一个bool类型的属性:AllowEdit表示可否编辑;IsReadOnly表示可否只读。不能编辑也可以理解为只读,因此这2个特性的作用是相同的,它们共同控制着ModelMetadata对象的IsReadOnly属性。在这里,EditableAttribute具有较高的优先级。

   (5)DisplayAttribute和DisplayNameAttribute

       DisplayAttribute特性为目标数据成员定义一些说明性文字,其字符串类型的Prompt属性为目标数据成员设置一个以水印显示的字符串。该特性还允许我们通过资源文件的方式来定义他们,DisplayAttribute特性类里面有一个类型为Type,名为ResourceType的属性,如果我们对这个属性赋值,那么Prompt等5个属性值(另4个是Name,ShortName,Description,Order,这些都是DisplayAttribute类里面的属性)将会被认为是对应的资源条目的名称。

       DisplayNameAttribute特性是专门设置目标元素的显示名称,通过DisplayName属性来设置,这个属性如果没在构造函数中初始化则为空字符串。这两个特性同样会涉及到ModelMetadata的属性。

public class DisplayNameAttribute:Attribute
{
    public DisplayNameAttribute();
    public DisplayNameAttribute(string displayName);
    public virtual  string DisplayName{get;}
}

   (6)RequiredAttribute

       最后一个特性功能是将目标元素设置为必需的数据成员,也就是做标注,对于应用了RequiredAttribute特性的数据成员,对应ModelMetadata的IsRequired属性被设置为true。

你可能感兴趣的:(asp.net Model元数据学习一)