天天看点

ASP.NET MVC的Model元数据提供机制的实现一、 ModelMetadataProvider二、DataAnnotationsModelMetadataProvider三、对Model元数据提供系统的扩展

注:在本文中提及的ModelMetadataProvider在大部分情况泛指直接或者间接继承自抽象类ModelMetadataProvider,用于提供Model元数据的提供者对象或者类型,请读者注意区分。

不过DataAnnotationsModelMetadataProvider并没有直接继承自ModelMetadataProvider,而是继承自抽象类AssociatedMetadataProvider,后者是ModelMetadataProvider的子类。AssociatedMetadataProvider的主要作用是对应用在Model类型或属性上所有“关联”的特性,这也是它命名的由来。如下面的代码片断所示,AssociatedMetadataProvider实现了定义在ModelMetadataProvider的三个方法。

对于AssociatedMetadataProvider实现的三个方法,它并紧紧是通过反射将应用在Model类型和对应属性上的所有特性,并将这个特性列表作为参数(attributes)传入抽象方法CreateMetadata完成Model元数据的创建。值得一提的是,当通过调用CreateMetadata创建出ModelMetadata之后,会从特性列表中筛选出实现了IMetadataAware接口的特性,并将该ModelMetadata对象作为参数调用它们的OnMetadataCreated方法。

继承自AssociatedMetadataProvider的DataAnnotationsModelMetadataProvider实现了抽象方法,它根据传入的特性列表以及其他相关的信息(用于创建Model对象的委托、容器和Model类型以及属性名称)实现对Model元数据的最终创建。下面的代码片断就是整个DataAnnotationsModelMetadataProvider类型的定义。

包含在Model元数据提供系统的ModelMetadataProvider、AssociatedMetadataProvider、DataAnnotationsModelMetadataProvider和ModelMetadataProviders与ModelMetadata之间的关系可以通过如下图所示的UML来体现。

ASP.NET MVC的Model元数据提供机制的实现一、 ModelMetadataProvider二、DataAnnotationsModelMetadataProvider三、对Model元数据提供系统的扩展

对Model元数据提供系统的扩展主要体现在对ModelMetadataProvider自定义上。基于标注特性的元数据定义方式最终是通过DataAnnotationsModelMetadataProvider来实现,通过自定义ModelMetadataProvider我们完全可以提供一种全新的Model元数据定义方式。不过我们经常使用的方式还是通过继承DataAnnotationsModelMetadataProvider在现有的元数据提供机制上做一些扩展。

为了将DisplayTextAttribute应用到Model元数据的初始化过程中,我们通过继承DataAnnotationsModelMetadataProvider创建了如下一个ExtendedDataAnnotationsProvider。在重写的CreateMetadata方法中,我们先调用基类的同名方法得到一个ModelMetadata对象。如果该对象的DisplayName属性为空,在从特性列表中获取DisplayTextAttribute特性并调用其SetDisplayName方法对ModelMetadata的DisplayName属性进行设置。

对于之前创建的演示实例,如果我们在Global.asax中通过如下的方式对我们自定义的ExtendedDataAnnotationsProvider进行注册,该实例应用同样可以正常运行。

这个实例直接使用了扩展的DataAnnotationsModelMetadataProvider替换了默认的CachedDataAnnotationsModelMetadataProvider,意味着失去了对成功解析出来的元数据的缓存功能,会对性能造成一定的影响。但是由于CachedDataAnnotationsModelMetadataProvider已经将CreateMetadata方法封闭(Seal),又不能直接继承CachedDataAnnotationsModelMetadataProvider。如果项目里面确实需要使用到类似的用法,可以考虑自己实现缓存。

作者:蒋金楠

微信公众账号:大内老A

如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

<a href="http://www.cnblogs.com/artech/archive/2012/05/09/model-metadata-provision.html" target="_blank">原文链接</a>