ModelValidator主要是應用在ModelMetadata元數據的類型上或類型屬性上。它是驗證的基礎類型,所有的ModelValidatorProviders、DataAnnotationValidator、DataAnnotationValidatorProvider都是主要通過GetVa ...
ModelValidator主要是應用在ModelMetadata元數據的類型上或類型屬性上。它是驗證的基礎類型,所有的ModelValidatorProviders、DataAnnotationValidator、DataAnnotationValidatorProvider都是主要通過GetValidators這個方法來獲取IEnumerable<ModelValidator>對象。然後迴圈這個迭代對象,利用ModelValidator的Validator對每個元數據進行驗證。有個例子可以很好的說明:
1 private IEnumerable<ModelValidator> GetValidator(Type type) 2 { 3 ModelValidatorProvider provider=new DataAnnodationModelValidatorProvider();
ModelMetaData metadata=ModelMetadataProviders.Current.GetMetadataForType(null,type);
foreach(var validator in provider.GetValidator(metadata,ControllerContext))
{
yeild return validator
}
foreach(var propertyMetadata in metadata.Properties)
{
foreach(var validator in provider.GetValidator(propertyMetadata,ControllerContext))
yeild return validator;
}
4 }
元數據ModelMetaData包含:IEnumrable<ModelValidator> GetValidator(ContollerContext) 實現方法:
IEnumrable<ModelValidator> GetValidator(ControllerContext context) { return ModelValidatorProviders.Providers.GetValidator(this,context) }
其中Providers來源:
private static readonly ModelValidatorProviderCollection _providers=new ModelValidatorProviderCollecton
{
new DataAnnotationModelValidatorProvider(),
new DataErrorInfoModelValidatorProvider(),
new ClinetDataTypeModelValidatorProvider()
}
繼續實現 Providets的GetValidator的方法:
public class ModelValidatorProviderCollection:ICollection<ModelValidatorProvider>
{
public IEnumrable<ModelValidator> GetValidator(ModelMedatata modeltadata,ControllerContext context)
{
return this.CombindItems.SelectMany(ModelValidatorProvider provider)=>provider.GetValidators(modeltadata,context);
//這個方法CombindItems可理解為內部已定義數據集合和外部自定義的數據集合的合計。具體的實現在MultiServiceResolver:IResolver<IEnumrable<TServerice>>中
}
//對了這個類我本來不想往下記錄下 但是為了以後再學習和本著研究的心態還是硬著頭皮寫寫去吧
public IResolver<IEnumrable<ModelValidatorProvider>> _serviceResolver;
privite IEnumeable<ModelValidator> CombindItems
{
get{
return this._serviceResoler.Current;
}
}
public ModelValidatorProviderCollection()
{
this._serviceResolver=new MultiServiceResolver<ModelValidatorProvider>(()=>this.Items);
}
public ModelValidatorProviderCollection(IList<ModelValidatorProvider> list):base(list);
{
this._serviceResolver=new MultiServerResolver<ModelValdatorProvider>(()=>this.Items);
}
internal ModelValidatorProviderCollection(IReslover<IEnumrable<ModelValidatorProvider>> services,Params ModelValidatorProvider[] modelValidatorProviders):base(modelValidatorProviders)
{
IResolver<IEnumrable<ModelValidaotProvider>> arge=services;
if(arge==null)
{
arge=new MultiServiceReslover<ModelValidatorProvider>(this.Items);
}
this._serviceResolber=arge;
}
prottect override void SetItem(int index,ModelValidatorProvider item)
{
if(item==null)
throw new ArgumentNullException("item");
base.SetItem(index,item);
}
}
//【下麵要介紹的是MultiServiceResolver類的只要實現,主要是通過依賴組件DependencyResolver.Current的GerServices<TService>得到一組數據,然後通過構造函數傳入的委托方法得到另外一組數據,通過Current實現兩組數據的結合】
public class MultiServiceReslover<TService>:IService<IEnumrable<TService>> where TService :Class
{
private Lazy<IEnumerable<TService>> _itemsFormService;
private Func<IEnumrable<IService>> _itemThunk;
private Func<IEnumrable<TService>> _resolverThunk;
public IEnumrable<TService> Current
{
get{
return this.itemsFormService.Value.Cacat(this._itemThunk());
}
}
public MultiServiceResolve(Func<IEnumrable<TService>> itemsThunk)
{
if(itemThunk==null)
throw new ArgumentNullException("itemThunk");
this._itemsThunk=itemsThunk;
this._resolverThunk=(()=>DependencyResolver.Curremt);
this._itemsFormServices=new Lazy<IEnumerable<TService>>(()=>this._resolverThunk.GetService<TService>());
}
}
前面一直圍繞著獲取ModelValidatorProvider來實現方法。可ModelValidatorProvider本身是一個抽象類和只有一個abstract的GetValidators(ModelMedata,ControllerContext)的方法。現在對系統中預設繼承和實現ModelValidatorProvider抽象類的其中一個比較常用的類型做說明,那就是 DataAnnotationModelValidatorProvider,它是系統間接實現了ModelValidatorProvider,是我們最常用的基於驗證特性的聲明式 Model 驗證。
在瞭解DataAnnotationModelValidatorProvider時 會提到DataAnnotationModelValidator這類,它具體地實現了ModelValidator定義的方法(包括Validate(object container))。
public class DataAnnotationModelValidatorProvider:AssocitatedValidatorProvider { //這裡只編輯主要的實現方法 // 這裡的DataAnnotationModelValidatorFactory的系統定義的一個委托。如果元數據屬性未定義在AttributeFactories中 則採用預設的ModelValidator對象 internal static DataAnnotationModelValidatorFactory DefaultAttributeFactory=(ModelMetaData metadata,ControllerContext context,ValidatorAttribute attrubute)=>new DataAnnotaionModelValidator(metadata,context,attribute); //主要為創建元數據"自我驗證"集合,可以通過RegisterValidatableObjectAdapter(Type modelType,Type adapterType)來實現自我註冊 internal static Dictionary<Type,DataAnnotationModelValidatorFactiory> AttributeFactories=DataAnnotationModelValidatorProvider.BuildAttributeFactoriesDictionary(); //接下來是最主要的代碼了 protext override IEnumerable<ModelValidator> GetValidators(ModelMetaData metadata,ControllerContext context,ValidatorAttribute attributes) { var result=new List<ModelValidator>; try{ //這一步的意思是: AddImplicitRequiredAttributeForValueTypes (為值類型添加隱式必填驗證) 值為True,元數據也聲明瞭Required=True,則必須在attributes里包含 RequiredAttribute if(DataAnnotatoonModelValidatorProvider.AddImplicitRequiredAttributeForValueType && metadata.IsRequired) { if(!attributes.Any((Attribute t)=>t is RequiredAttribute)) { attrubutes=attribites.concat(new RequiredAttribute[]{new RequiredAttrbute()}); } } foreach(var ValidatorAttribute current in attributes.ofType<ValidatorAttribute>) { DataAnnotationModelValidatorFactory defaultFactory; if(!DataAnnotationModelValidatorProvider.AttrbuteFactories.TryValue(current.GetType(),out defualtFactory)) { defaultFactory=DataAnnotationModelValidatorProvider.DefaultAttrbuteFactoty; } result.Add(defaultFactory(metadata,context,current)) } if(typeof(IValidatableObject).IsAssignableForm(medatat.ModelType)) { DataAnnotationsValidatableObjectAdapterFactory defaultValidatableFactory; if (!DataAnnotationsModelValidatorProvider.ValidatableFactories.TryGetValue(metadata.ModelType, out defaultValidatableFactory)) { defaultValidatableFactory = DataAnnotationsModelValidatorProvider.DefaultValidatableFactory; } result.Add(defaultValidatableFactory(metadata, context)); } } finally{ } return result; } //上面這個方法寫了這麼多無非就是 根據元數據上的屬性獲取繼承了ModelValidator的對象集合,然後利用集合里每個對象所定義的Validator方法進行驗證 //下麵是一些自定義註冊方法 public static void RegistAdapter(Type attrbuteType,Type adaperType) { //獲取當前 adaperType的特定構造函數 ConstructorInfo constructor=adapterType.GetConstructor(typeOf(ModelMetadata),typeof(ControllerContext),attrbuteType); try{ DataAnnotationModelValidatorProvider.AttributeFacties[attrbuteType]=((ModelMedatada metadata,ControllerContext context,ValidatorAttribute attribute)=>(ModelValidator)constructor.Invoker(new object[]{metadata,context,attrbute})); } finally{ } } //直接用委托方法註冊 public static void RegisterAdapterFactory(Type attributeType,DataAnnotationsModelValidatorFactory factory) BuildAttributeFacoriesDictionary { //還有好多自定義註冊方法 反編譯後查看吧 //下麵實現的是系統自定義一些ValidatorAttribute private static Dictionary<Type,DataAnnotationModelValidatorFactory> dictionary=new Dictionary<Type,DataAnnotationModelValidatorFactory>(); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, typeof(RangeAttribute), (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new RangeAttributeAdapter(metadata, context, (RangeAttribute)attribute)); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, typeof(RegularExpressionAttribute), (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute)); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, typeof(RequiredAttribute), (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute)); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, typeof(StringLengthAttribute), (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new StringLengthAttributeAdapter(metadata, context, (StringLengthAttribute)attribute)); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, ValidationAttributeHelpers.MembershipPasswordAttributeType, (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new MembershipPasswordAttributeAdapter(metadata, context, attribute)); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, ValidationAttributeHelpers.CompareAttributeType, (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new CompareAttributeAdapter(metadata, context, attribute)); DataAnnotationsModelValidatorProvider.AddValidationAttributeAdapter(dictionary, ValidationAttributeHelpers.FileExtensionsAttributeType, (ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) => new FileExtensionsAttributeAdapter(metadata, context, attribute)); DataAnnotationsModelValidatorProvider.AddDataTypeAttributeAdapter(dictionary, ValidationAttributeHelpers.CreditCardAttributeType, "creditcard"); DataAnnotationsModelValidatorProvider.AddDataTypeAttributeAdapter(dictionary, ValidationAttributeHelpers.EmailAddressAttributeType, "email"); DataAnnotationsModelValidatorProvider.AddDataTypeAttributeAdapter(dictionary, ValidationAttributeHelpers.PhoneAttributeType, "phone"); DataAnnotationsModelValidatorProvider.AddDataTypeAttributeAdapter(dictionary, ValidationAttributeHelpers.UrlAttributeType, "url"); return dictionary; } }
上面這個類引用了之類AssociatedValidatorProvider Associated(關聯的意思)。這個類首先利用GetValidator(ModelMetadata,ControllerContext) 對元數據提取Attribute, 得到的Attribute數組去調用抽象方法GetValidator(ModelMetadata,ControllerContext,IEnumrable<ModelValidator>),這個方法在上面的DataAnnotationModelValidatorProvider被實現。
AssociatedValidatorProvider類重點對傳入的元數據ModelMetadata進行解析。
public sealed override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata,ControllerContext context) { if(metadata==null) throw new ArgumentNullExecption("metadata"); if(context==null) throw new ArgumentNullExecption("context"); } protect abstract IEnumrable<ModelValidator> GetValidators(ModelMetadata,ControllerContext,IEunmerable<Attribute> atttibutes);//這個抽象方法在上面類(DataAnnotationModelValidatorProvider)里有具體的實現 protected override ICustomTypeDescriptor GetTypeDescriptor(Type type) { return TypeDescriptorHepler.Get(type); } pritvate IEnumerable<ModelValidator> GetValidatorForProperty(ModelMetadata metadata,ControllerContextg context) { IcustomTypeDescriptor typedescriptor=this.GetTypeDescriptor(metadata.ContainerType); PropertyDescriptor propertyDescriptor=typedescriptor.GetProperties.Find(metadata.PropertyName,true); if(propertyDescriptor==null) throw new ArgumentException("PropertyNoFound"); return this.GetValidator(metadata,context,propertyDescriptor.Attributes.OfType<Attribute>); } private IEnumerable<ModelValidator> GetValidatorsForType(MedelMetadata metadata,ControllerContext context) { return this.GetValidator(metadata,context,this.GetTypeDescriptor(metadata.ModelType).GetAttributes().Cast<Attribue>); }
上面的DataAnnotationModelValidatorProvider中 根據屬性來查找實現委托DataAnnotationsModelValidationFactory時,有一個預設的實現:DataAnnotationsModelValidator。這個方法是真正實現了驗證功能Validate(object contatiner).
下麵就是這個類大概的實現過程。
public class DataAnnotationModelValidator:ModelValidator { public override IEnumerable<ModelValidatorResult> Validate(object container) { ValidationContext validationContext=new ValidationContext(container??base.Metadata.Model,null,null); validationContext.DisplayName=this.Metadata.DisPlayName(); validationResult result=this.Attribute.GetValidationResult(base.Metadata.Model,validationContext); if(result!=result.Scuess) { yeild return New ModelValidateResult
{ Message=validation.ErrorMessage; }; yeild break; } } protect internal string ErrorMessage { get{ return this.Attribute.FormatErrorMessage(base.Metadata.DispalyName()); } } }