ASP.NET MVC基於標注特性的Model驗證:DataAnnotationsModelValidatorProvider


DataAnnotationsModelValidator最終是通過它對應的ModelValidatorProvider,即DataAnnotationsModelValidatorProvider創建的。通過前面的介紹我們知道它是AssociatedValidatorProvider的子類,后者在用於獲取ModelValidator的GetValidators方法中已經根據指定的Model元數據所有特性創建出來,DataAnnotationsModelValidator只需要從中篩選出繼承自ValiationAttribute的驗證特性並創建對象的DataAnnotationsModelValidator就可以了。[本文已經同步到《How ASP.NET MVC Works?》中]

目錄
DataAnnotationsModelValidator
基於ValidationAttribute的ModelValidator的創建
基於IValidatableObject的ModelValidator的創建
默認的ModelValidator創建機制
對ModelValidator創建方式的定制

DataAnnotationsModelValidator

我們現在結合DataAnnotationsModelValidator的相關定義來討論一下具體的ModelValidator提供機制。如下面的代碼片斷所示,DataAnnotationsModelValidatorProvider具有兩個靜態的字段AttributeFactories和DefaultAttributeFactory,后者是一個DataAnnotationsModelValidationFactory委托,前者是以此委托為Value以Type對象為Key的字典。

   1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
   2: {
   3:     //其他成員
   4:     internal static readonly Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories;
   5:     internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory;
   6:  
   7:     internal static DataAnnotationsValidatableObjectAdapterFactory DefaultValidatableFactory;
   8:     internal static readonly Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory> ValidatableFactories;
   9:     
  10:     protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, HttpActionContext actionContext, IEnumerable<Attribute> attributes);
  11: }
  12:  
  13: public delegate ModelValidator DataAnnotationsModelValidationFactory(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute);
  14:  
  15: public delegate ModelValidator DataAnnotationsValidatableObjectAdapterFactory(ModelMetadata metadata, ControllerContext context);

基於ValidationAttribute的ModelValidator的創建

委托DataAnnotationsModelValidationFactory根據ModelMetadata、ControllerContext和ValidationAttribute返回一個ModelValidator對象,而字段AttributeFactories表示的字典對象的Key是具體的驗證特性的類型,也就是說它維護一個ValidationAttribute特性類型和對應ModelValidator工廠的匹配關系。在重寫的GetValidators方法中,針對指定的每一個ValidationAttribute,它先根據其類型從AttributeFactories中獲取一個對應的DataAnnotationsModelValidationFactory委托,如果該委托存在,則用它來創建相應的ModelValidator對象;否則就采用字段DefaultAttributeFactory表示的DataAnnotationsModelValidationFactory委托來進行ModelValidator的創建

基於IValidatableObject的ModelValidator的創建

除了AttributeFactories和DefaultAttributeFactory,DataAnnotationsModelValidatorProvider還具有DefaultValidatableFactory和ValidatableFactories這兩個靜態屬性,它們用於針對可驗證對象(實現了IValidatableObject接口)的ModelValidator的創建。DataAnnotationsModelValidator的類型是另外一個類型為DataAnnotationsValidatableObjectAdapterFactory的委托,該委托根據ModelMetadata和ControllerContext創建相應的ModelValidator。ValidatableFactories是一個以此委托為Value,以Type對象為Key的字典。

當DataAnnotationsModelValidatorProvider完成了針對基於驗證特性的ModelValidator的創建之后,如果根據Model元數據解析出來的Model類型實現了IValidatableObject接口,那么先從字典ValidatableFactories中根據此類型獲取一個對應的DataAnnotationsValidatableObjectAdapterFactory委托,如果匹配的委托對象存在,則用其進行ModelValidator的創建;否則采用通過字段DefaultValidatableFactory表示的默認工廠來創建相應的ModelValidator對象

默認的ModelValidator創建機制

在DataAnnotationsModelValidatorProvider類型被加載的時候,上述的四個字段會在靜態構造函數調用時被初始化。從如下的代碼片斷可看出,對於一般的ValidationAttribute,對應的ModelValidator是一個DataAnnotationsModelValidator對象(DefaultAttributeFactory字段);針對RangeAttribute、RegularExpressionAttribute 、RequiredAttribute和StringLengthAttribute這四種驗證特性,它們對應的適配ModelValidator會被創建出來。而對於可驗證對象來說,默認情況下提供的ModelValidator列表中還包含一個ValidatableObjectAdapter對象。

   1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
   2: {
   3:     //其他成員
   4:     static DataAnnotationsModelValidatorProvider()
   5:     {
   6:         //1、DefaultAttributeFactory
   7:         DefaultAttributeFactory = (metadata, context, attribute) => new DataAnnotationsModelValidator(metadata, context, attribute);
   8:  
   9:         //2、AttributeFactories
  10:         Dictionary<Type, DataAnnotationsModelValidationFactory> dictionary = new Dictionary<Type, DataAnnotationsModelValidationFactory>();
  11:         dictionary.Add(typeof(RangeAttribute), (metadata, context, attribute) => new RangeAttributeAdapter(metadata, context, (RangeAttribute)attribute));
  12:         dictionary.Add(typeof(RegularExpressionAttribute), (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute));
  13:         dictionary.Add(typeof(RequiredAttribute), (metadata, context, attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute));
  14:         dictionary.Add(typeof(StringLengthAttribute), (metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context,(StringLengthAttribute)attribute));
  15:         AttributeFactories = dictionary;
  16:  
  17:         //3、DefaultValidatableFactory
  18:         DefaultValidatableFactory = (metadata, context) => new ValidatableObjectAdapter(metadata, context);
  19:  
  20:         //4、ValidatableFactories
  21:         ValidatableFactories = new Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>();
  22:     }
  23: }

對ModelValidator創建方式的定制

DataAnnotationsModelValidatorProvider四個基於委托的靜態字段體現了其采用的ModelValidator提供機制。由於它們都是內部字段,我們不能直接對其進行操作,但是如下所示的一系列靜態方法在DataAnnotationsModelValidatorProvider中定義出來,使我們可以按照具體的需要對默認的ModelValidator進行定義。

   1: public class DataAnnotationsModelValidatorProvider : AssociatedValidatorProvider
   2: {
   3:     //其他成員  
   4:    public static void RegisterAdapter(Type attributeType, Type adapterType);
   5:    public static void RegisterAdapterFactory(Type attributeType, DataAnnotationsModelValidationFactory factory);
   6:    public static void RegisterDefaultAdapter(Type adapterType);
   7:    public static void RegisterDefaultAdapterFactory(DataAnnotationsModelValidationFactory factory);
   8:  
   9:    public static void RegisterDefaultValidatableObjectAdapter(Type adapterType);
  10:    public static void RegisterDefaultValidatableObjectAdapterFactory(DataAnnotationsValidatableObjectAdapterFactory factory);
  11:    public static void RegisterValidatableObjectAdapter(Type modelType, Type adapterType);
  12:    public static void RegisterValidatableObjectAdapterFactory(Type modelType, DataAnnotationsValidatableObjectAdapterFactory factory);
  13: }

對於上面的8個靜態方法,除了RegisterDefaultAdapter和RegisterValidatableObjectAdapter之外,其余的都很好理解。RegisterDefaultAdapter用於注冊一個默認的針對驗證特性的ModelValidator類型,該類型必須具有一個參數類型列表為ModelMetadata、ControllerContext和Attribute的構造函數。如果根據 驗證特性的類型找到了匹配的DataAnnotationsModelValidationFactory委托對象,相應的參數會被傳入該構造函數並最終創建一個我們注冊的ModelValidator對象。

RegisterValidatableObjectAdapter和RegisterDefaultAdapter比較類似,用於注冊一個默認的針對可驗證對象類型的ModelValidator,有該類型必須具有一個參數類型列表為ModelMetadata和ControllerContex的構造函數。如果根據 驗證特性的類型找到了匹配的DataAnnotationsValidatableObjectAdapterFactory委托對象,相應的參數會被傳入該構造函數並最終創建一個我們注冊的ModelValidator對象。

ASP.NET MVC基於標注特性的Model驗證:ValidationAttribute
ASP.NET MVC基於標注特性的Model驗證:DataAnnotationsModelValidator
ASP.NET MVC基於標注特性的Model驗證:DataAnnotationsModelValidatorProvider
ASP.NET MVC基於標注特性的Model驗證:將ValidationAttribute應用到參數上
ASP.NET MVC基於標注特性的Model驗證:一個Model,多種驗證規則


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM