前情回顾:
上一篇 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,IValidateResult> ValidateFunc { get; set; }
public IValidateResult Validate(ValidateContext context)
{
ParamHelper.CheckParamNull(ValidateFunc,"ValidateFunc","Can't be null");
ParamHelper.CheckParamNull(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以及扩展方法实现