Asp.net MVC源码分析--Model Validation(Server端)实现(2)
前面我们介绍了Model Validation的用法,以及ValidateModel的方法实现,这一篇我们来详细学习一下DataAnnotationsModelValidatorProvider类的实现。
三.DataAnnotationsModelValidatorProvider类详解
1.AttributeFactories对象
首先在这个类中可以看到在初始化时创建了AttributeFactories对象(Dictionary), 这个集合包含了系统内置一些验证规则。
1 internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>() {
2 {
3 typeof(RangeAttribute),
4 (metadata, context, attribute) => new RangeAttributeAdapter(metadata, context, (RangeAttribute)attribute)
5 },
6 {
7 typeof(RegularExpressionAttribute),
8 (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute)
9 },
10 {
11 typeof(RequiredAttribute),
12 (metadata, context, attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute)
13 },
14 {
15 typeof(StringLengthAttribute),
16 (metadata, context, attribute) => new StringLengthAttributeAdapter(metadata, context, (StringLengthAttribute)attribute)
17 },
18 }
19 }
复制代码
2.ValidationAttribte 的 Adapter 设计模式应用
这里特别需要注意的是MVC利用了*AttributeAdapter 把 ValidationAttribte 的GetValidationResult方法和 ModelValidator.Validate方法作了一个适配(这里用到Adapter模式)请看RangeAttributeAdapter/RegularExpressionAttributeAdapter/RequiredAttributeAdapter/StringLengthAttributeAdapter
请参照DataAnnotationsModelValidator.Validate 方法源码,第7行代码,就是在这里进行了适配的工作。
1 public override IEnumerable<ModelValidationResult> Validate(object container) {
2 // Per the WCF RIA Services team, instance can never be null (if you have
3 // no parent, you pass yourself for the "instance" parameter).
4 ValidationContext context = new ValidationContext(container ?? Metadata.Model, null, null);
5 context.DisplayName = Metadata.GetDisplayName();
6
7 ValidationResult result = Attribute.GetValidationResult(Metadata.Model, context);
8 if (result != ValidationResult.Success) {
9 yield return new ModelValidationResult {
10 Message = result.ErrorMessage
11 };
12 }
13 }
复制代码
3.获取ModelValidator对象集合
接下来我们来分析一下DataAnnotationsModelValidatorProvider.GetValidators 方法的实现
1 protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes) {
2 _adaptersLock.EnterReadLock();
3
4 try {
5 List<ModelValidator> results = new List<ModelValidator>();
6
7 // Add an implied [Required] attribute for any non-nullable value type,
8 // unless they've configured us not to do that.
9 if (AddImplicitRequiredAttributeForValueTypes &&
10 metadata.IsRequired &&
11 !attributes.Any(a => a is RequiredAttribute)) {
12 attributes = attributes.Concat(new[] { new RequiredAttribute() });
13 }
14
15 // Produce a validator for each validation attribute we find
16 foreach (ValidationAttribute attribute in attributes.OfType<ValidationAttribute>()) {
17 DataAnnotationsModelValidationFactory factory;
18 if (!AttributeFactories.TryGetValue(attribute.GetType(), out factory)) {
19 factory = DefaultAttributeFactory;
20 }
21 results.Add(factory(metadata, context, attribute));
22 }
23
24&nbs
补充:Web开发 , ASP.Net ,