首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC DataAnnotationsModelValidatorProvider 核心機制與擴充點深度解析

     編輯:關於ASP.NET

簡介

DataAnnotationsModelValidatorProvider 是 ASP.NET MVC 預設最重要的 ModelValidatorProvider,負責將 ValidationAttribute 轉換為對應的 ModelValidator。本文深入剖析其內部工廠機制與擴充介面。

核心靜態工廠字典

類別內部維護四組靜態工廠委派與字典:

欄位型別用途
AttributeFactoriesDictionary<Type, DataAnnotationsModelValidationFactory>特定 ValidationAttribute 型別對應的自訂 ModelValidator 工廠
DefaultAttributeFactoryDataAnnotationsModelValidationFactory預設工廠,建立通用 DataAnnotationsModelValidator
ValidatableFactoriesDictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>實作 IValidatableObject 的型別對應工廠
DefaultValidatableFactoryDataAnnotationsValidatableObjectAdapterFactory預設 IValidatableObject 適配器工廠,建立 ValidatableObjectAdapter

預設註冊對應關係(靜態建構子)

static DataAnnotationsModelValidatorProvider()
{
    // 1. 預設 ValidationAttribute 工廠
    DefaultAttributeFactory = (metadata, context, attribute) => new DataAnnotationsModelValidator(metadata, context, attribute);

    // 2. 內建四大屬性專用適配器
    var dict = new Dictionary<Type, DataAnnotationsModelValidationFactory>();
    dict.Add(typeof(RangeAttribute), (m, c, a) => new RangeAttributeAdapter(m, c, (RangeAttribute)a));
    dict.Add(typeof(RegularExpressionAttribute), (m, c, a) => new RegularExpressionAttributeAdapter(m, c, (RegularExpressionAttribute)a));
    dict.Add(typeof(RequiredAttribute), (m, c, a) => new RequiredAttributeAdapter(m, c, (RequiredAttribute)a));
    dict.Add(typeof(StringLengthAttribute), (m, c, a) => new StringLengthAttributeAdapter(m, c, (StringLengthAttribute)a));
    AttributeFactories = dict;

    // 3. IValidatableObject 預設工廠
    DefaultValidatableFactory = (metadata, context) => new ValidatableObjectAdapter(metadata, context);
    ValidatableFactories = new Dictionary<Type, DataAnnotationsValidatableObjectAdapterFactory>();
}

GetValidators 執行流程

  1. 從 ModelMetadata 取得所有 Attribute。
  2. 篩選繼承自 ValidationAttribute 的屬性。
  3. 對每個屬性:
    • 先從 AttributeFactories 查找型別專用工廠。
    • 找不到則用 DefaultAttributeFactory。
    • 呼叫工廠建立 ModelValidator 加入結果集。
  4. 若 Model 型別實作 IValidatableObject:
    • 從 ValidatableFactories 查找型別專用工廠。
    • 找不到用 DefaultValidatableFactory。
    • 建立對應 Validator 加入結果。

公開擴充方法(8 個靜態註冊方法)

雖然工廠字典為 internal,但提供公開靜態方法供開發者註冊自訂適配器:

// ValidationAttribute 適配器註冊
public static void RegisterAdapter(Type attributeType, Type adapterType);
public static void RegisterAdapterFactory(Type attributeType, DataAnnotationsModelValidationFactory factory);
public static void RegisterDefaultAdapter(Type adapterType);
public static void RegisterDefaultAdapterFactory(DataAnnotationsModelValidationFactory factory);

// IValidatableObject 適配器註冊
public static void RegisterValidatableObjectAdapter(Type modelType, Type adapterType);
public static void RegisterValidatableObjectAdapterFactory(Type modelType, DataAnnotationsValidatableObjectAdapterFactory factory);
public static void RegisterDefaultValidatableObjectAdapter(Type adapterType);
public static void RegisterDefaultValidatableObjectAdapterFactory(DataAnnotationsValidatableObjectAdapterFactory factory);

關鍵差異說明

  • RegisterAdapter:指定 attributeType 對應的 adapterType,該型別需有 (ModelMetadata, ControllerContext, ValidationAttribute) 建構子。
  • RegisterAdapterFactory:直接提供工廠委派,彈性最高。
  • RegisterDefaultAdapter:設定預設適配器型別(用於無專用適配器的 Attribute)。
  • RegisterValidatableObjectAdapter:針對特定 modelType 註冊 IValidatableObject 適配器,建構子為 (ModelMetadata, ControllerContext)。

實戰應用:自訂驗證屬性與客戶端規則

若自訂 AgeRangeAttribute : ValidationAttribute, IClientValidatable,需:

  1. 實作伺服器端 IsValid。
  2. 2. 實作 GetClientValidationRules 產生 ModelClientValidationRule。 3. 註冊伺服器端適配器:DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(AgeRangeAttribute), typeof(AgeRangeAttributeAdapter)); 4. AgeRangeAttributeAdapter 繼承 DataAnnotationsModelValidator<AgeRangeAttribute> 並覆寫 GetClientValidationRules 回傳前端規則。

總結

DataAnnotationsModelValidatorProvider 採用工廠模式解耦屬性與 Validator 建立邏輯,靜態字典提供高效查找,公開註冊方法開放完整擴充點。掌握其機制可輕鬆整合自訂驗證屬性、客戶端規則或替換預設行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved