上一篇 1) 接口介紹以及總體思路概述 簡單描述了下庫的設(shè)計思路
本文將說說驗證器實現(xiàn),歡迎大神指導(dǎo)更快更好的方案
我們首先從用戶調(diào)用的驗證器開始實現(xiàn),所以我們應(yīng)該首先這樣做
public class Validator : IValidator{ public IValidateResult Validate(ValidateContext context) { }}但是我們的驗證器不是沒有規(guī)則嘛?回憶一下我們好像是在為 Fluent 設(shè)計時添加了一個驗證器設(shè)置規(guī)則的接口,所以我們應(yīng)這樣實現(xiàn)驗證器:
public class Validator : IValidatorSetter{ PRivate List<IValidateRule> m_Rules = new List<IValidateRule>(); // 保存驗證規(guī)則 public void SetRules(IEnumerable<IValidateRule> rules) { ParamHelper.CheckParamNull(rules, "rules", "Can't be null"); m_Rules.AddRange(rules); // 添加驗證規(guī)則 } 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(); } // 處理驗證規(guī)則分組標(biāo)志篩選列表 var rules = m_Rules.Where(i => context.RuleSelector.CanExecute(i, context)).ToArray(); // 篩選驗證規(guī)則 var result = Container.Resolve<IValidateResult>(); if (!rules.IsEmptyOrNull()) { var tasks = rules.Select(i => Task.Factory.StartNew(() => i.Validate(context))).ToArray(); Task.WaitAll(tasks); // 執(zhí)行驗證 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); // 處理 驗證結(jié)果 } return result; }}
接著我們再實現(xiàn)驗證規(guī)則:
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); // 執(zhí)行規(guī)則的驗證 } else { result = Container.Resolve<IValidateResult>(); } return result; } public IValidateResult ValidateByFunc(ValidateContext context) { IValidateResult result = ValidateFunc(context, ValueName, Error); //執(zhí)行當(dāng)前規(guī)則的驗證邏輯 var nextRule = NextRule; if (nextRule != null && (result.IsValid || context.Option == ValidateOption.Continue)) // 判斷是否有必要執(zhí)行子級驗證規(guī)則 { var nextResult = nextRule.Validate(context); // 執(zhí)行子級驗證規(guī)則 result.Merge(nextResult.Failures); // 處理子級驗證結(jié)果 } return result; }}
等等,好像我們還沒有實現(xiàn)驗證規(guī)則分組標(biāo)志篩選器,好吧,我們實現(xiàn)它吧
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); }}
我們把目前的實現(xiàn)與接口綁定到容器中:
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 });// 簡單設(shè)置驗證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);
好吧,沒有實現(xiàn) Fluent 設(shè)置驗證規(guī)則的代碼,現(xiàn)在整體看起來真丑啊
NEXT: 3) Fluent以及擴展方法實現(xiàn)
新聞熱點
疑難解答