转载

实现一个对象验证库系列 -- 2) 验证器实现 (请大神批评)

前情回顾:

上一篇 1) 接口介绍以及总体思路概述 简单描述了下库的代码结构

本文将说说验证器实现,欢迎大神指导更快更好的方案

2) 验证器实现

我们首先从用户调用的验证器开始实现,所以我们应该首先这样做

public class Validator : IValidator {  public IValidateResult Validate(ValidateContext context)  {  } }

但是我们的验证器不是没有规则嘛?回忆一下我们好像是在为 Fluent 设计时添加了一个验证器设置规则的接口,所以我们应这样实现验证器:

public class Validator : IValidatorSetter {  private List<IValidateRule> m_Rules     = new List<IValidateRule>();  // 保存验证规则   public void SetRules(IEnumerable<IValidateRule> rules)  {   ParamHelper.CheckParamNull(rules, "rules", "Can't be null");   m_Rules.AddRange(rules);  // 添加验证规则  }   public IValidateResult Validate(ValidateContext context)  {   ParamHelper.CheckParamNull(context, "context", "Can't be null");      var list = context.RuleSetList;   if (!list.IsEmptyOrNull())   {    context.RuleSetList = list.Where(i => !string.IsNullOrEmpty(i)).Select(i => i.ToUpper()).ToArray();   }   // 处理验证规则分组标志筛选列表      var rules = m_Rules.Where(i => context.RuleSelector.CanExecute(i, context)).ToArray();   // 筛选验证规则         var result = Container.Resolve<IValidateResult>();   if (!rules.IsEmptyOrNull())   {    var tasks = rules.Select(i => Task.Factory.StartNew(() => i.Validate(context))).ToArray();    Task.WaitAll(tasks);    // 执行验证     if (tasks.Any(i => i.IsFaulted))    {     var exceptions = tasks.Where(i => i.IsFaulted)          .Select(i => i.Exception);     throw new AggregateException(exceptions);    }    // 处理task 的异常情况     var failures = tasks.Where(i => i.IsCompleted)         .SelectMany(i => i.Result.Failures);    result.Merge(failures);    // 处理 验证结果   }    return result;  } }

接着我们再实现验证规则:

public class ValidateRule : IValidateRule {  public IValidateRule NextRule { get; set; }   public string RuleSet { get; set; }   public string ValueName { get; set; }   public string Error { get; set; }   public Func<ValidateContext, bool> Condition { get; set; }   public Func<ValidateContext, string, string, IValidateResult> ValidateFunc { get; set; }   public IValidateResult Validate(ValidateContext context)  {   ParamHelper.CheckParamNull(ValidateFunc, "ValidateFunc", "Can't be null");   ParamHelper.CheckParamNull(context, "context", "Can't be null");   IValidateResult result = null;   if (Condition == null || Condition(context))  // 判断用户的特殊过滤条件   {    result = ValidateByFunc(context);      // 执行规则的验证   }   else   {    result = Container.Resolve<IValidateResult>();   }   return result;  }   public IValidateResult ValidateByFunc(ValidateContext context)  {   IValidateResult result = ValidateFunc(context, ValueName, Error); //执行当前规则的验证逻辑      var nextRule = NextRule;   if (nextRule != null    && (result.IsValid || context.Option == ValidateOption.Continue))  // 判断是否有必要执行子级验证规则   {    var nextResult = nextRule.Validate(context);  // 执行子级验证规则    result.Merge(nextResult.Failures);      // 处理子级验证结果   }    return result;  } }

等等,好像我们还没有实现验证规则分组标志筛选器,好吧,我们实现它吧

public class RuleSelector : IRuleSelector {  public bool CanExecute(IValidateRule rule, ValidateContext context)  {   return string.IsNullOrEmpty(rule.RuleSet)    || context.RuleSetList.IsEmptyOrNull()     ? true     : context.RuleSetList.Contains(rule.RuleSet);  } }

我们把目前的实现与接口绑定到容器中:

public static class Container {  public static ILifetimeScope CurrentScope { get; set; }   public static void Init(Action<ContainerBuilder> action)  {   ParamHelper.CheckParamNull(action, "action", "Can't be null");   Clear();   var builder = new ContainerBuilder();   action(builder);   var container = builder.Build();   CurrentScope = container.BeginLifetimeScope();  }   public static void Init()  {   Init(builder =>   {    // 绑定接口    builder.RegisterType<RuleSelector>().As<IRuleSelector>().SingleInstance();    builder.Register(c => new ValidateContext() { RuleSelector = c.Resolve<IRuleSelector>() });    builder.RegisterType<ValidateRule>().As<IValidateRule>().InstancePerDependency();    builder.RegisterType<ValidateResult>().As<IValidateResult>().InstancePerDependency();    builder.RegisterType<Validator>().As<IValidatorSetter>().InstancePerDependency();   });  }   public static void Clear()  {   var scope = CurrentScope;   if (scope != null)    scope.Dispose();  }   public static T Resolve<T>()  {   return CurrentScope.Resolve<T>();  } }

好吧,我们来简单试试吧:

Container.Init(); // 初始接口  var v = new Validator(); var rule = new ValidateRule() {  ValidateFunc = (c, name, error) =>  {   var f = new ValidateFailure()   {    Name = name,    Error = error,    Value = c   };   return new ValidateResult(new List<ValidateFailure>() { f });  } }; v.SetRules(new List<ValidateRule>() { rule }); // 简单设置验证   var context = new ValidateContext() { RuleSelector = new RuleSelector() }; var result = v.Validate(context); // 试用一下  Assert.IsNotNull(result); Assert.True(result.IsValid); Assert.IsNotNull(result.Failures); Assert.AreEqual(0, result.Failures.Count);

好吧,没有实现 Fluent 设置验证规则的代码,现在整体看起来真丑啊

NEXT: 3) Fluent以及扩展方法实现

正文到此结束
Loading...