验证API
本篇定位在数据入口的验证
- 普通的DataAnnotation验证
- 基于场景的DataAnnotation验证
- 可修改的外置式DataAnnotation验证
SUMMARY
最终调用时的用法:
class Program { static void Main(string[] args) { A2DFramework.Starter.Init(); A2DFramework.RuleEngine.Starter.Init(); A2DFramework.BusinessExceptionService.Starter.Init(); User user = new User(); user.FirstName = "aaa"; user.CustomField = "aaron"; foreach (var error in user.IsValid()) { Console.WriteLine(error.Key); } Console.WriteLine("==================="); foreach (var error in user.IsValid("场景1")) { Console.WriteLine(error.Key); Console.WriteLine(error.Message); } Console.ReadKey(); } }
原理:
基于场景的验证特性实现,举例:RuleDataTypeAttribute
RuleDataTypeAttribute,也就是DataTypeAttribute的场景支持版:
/// <summary> /// 支持规则场景的验证基类 /// </summary> public class RuleValidationAttribute : ValidationAttribute { public RuleValidationAttribute() { this.RuleName = string.Empty; } public RuleValidationAttribute(string rule) { this.RuleName = rule; } public string RuleName { get; set; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { return base.IsValid(value, validationContext); } } public class RuleDataTypeAttribute : RuleValidationAttribute { private DataTypeAttribute checker; public RuleDataTypeAttribute(DataType dataType):this(string.Empty, dataType) { } public RuleDataTypeAttribute(string rule, DataType dataType):base(rule) { checker = new DataTypeAttribute(dataType); } public RuleDataTypeAttribute(string rule, string customDataType) : base(rule) { checker = new DataTypeAttribute(customDataType); } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { return checker.GetValidationResult(value, validationContext); } }
至于基于RuleName的执行验证代码,核心代码:
List<BrokenRule> errors = new List<BrokenRule>(); var descriptor = GetTypeDescriptor(t); foreach (PropertyDescriptor propertyDescriptor in descriptor.GetProperties()) { foreach (var validationAttribute in propertyDescriptor.Attributes.OfType<ValidationAttribute>()) { RuleValidationAttribute baseAttr = validationAttribute as RuleValidationAttribute; if (baseAttr != null) { //支持场景验证 if (baseAttr.RuleName.Equals(scene, StringComparison.OrdinalIgnoreCase)) { ValidateProperty(o, errors, propertyDescriptor, validationAttribute); } } else { //不支持场景的验证 ValidateProperty(o, errors, propertyDescriptor, validationAttribute); } } } private void ValidateProperty(object o, List<BrokenRule> errors, PropertyDescriptor propertyDescriptor, ValidationAttribute validationAttribute) { object obj = propertyDescriptor.GetValue(o); ValidationContext ctx = new ValidationContext(o, null, null); ValidationResult result = validationAttribute.GetValidationResult(obj, ctx); if (result != ValidationResult.Success) { BrokenRule error = new BrokenRule(); error.Key = propertyDescriptor.Name; error.Message = validationAttribute.FormatErrorMessage(propertyDescriptor.Name); errors.Add(error); } }
上述代码是实现C#硬编码的验证逻辑,关于外置验证逻辑其实就是上述的另外一份拷贝,只是把里面的某些函数redirect到xml中,略。
具体文本验证逻辑的执行是通过调用js引擎实现,都比较简单。
稍微修改就能实现分布式和统一管理。