实现一个对象验证库系列 -- 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以及扩展方法实现

时间: 2024-10-06 02:15:13

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

实现一个对象验证库系列 -- 3) Fluent以及扩展方法实现 (请大神批评)

前情回顾: 上一篇 2) 验证器实现 简单描述了下验证器的简单实现 本文将说说Fluent方式的实现,欢迎大神们指点指点 3) Fluent以及扩展方法实现 我们按照之前 Fluent 的设想以及我们解耦的方式,所以我们先实现一个创建验证器创建者的静态类: public static class Validation { public static IValidatorBuilder<T> NewValidatorBuilder<T>() // 创建验证器创建者 { return

jQuery.Validate验证库

一.用前必备 官方网站:http://bassistance.de/jquery-plugins/jquery-plugin-validation/ API: http://jquery.bassistance.de/api-browser/plugins.html 当前版本:1.5.5 需要JQuery版本:1.2.6+, 兼容 1.3.2 二.默认校验规则 (1)required:true 必输字段 (2)remote:"check.php" 使用ajax方法调用check.php

jQuery.Validate验证库的使用介绍

jQuery.Validate验证库1.下载jquery.validate,这里我提供jquery-validation-1.9.0,点击下载 默认校验规则 (1)required:true               必输字段(2)remote:"check.php"          使用ajax方法调用check.php验证输入值(3)email:true                  必须输入正确格式的电子邮件(4)url:true                    必

humlbe bundle如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器?

一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接 humlbe bundle如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器? 二次验证码小程序于谷歌身份验证器APP的优势(更多见官网) 1.无需下载app 2.验证码丢失后可找回 3.手机丢失后,可从其他手机登陆微信找回验证码,防止被别有用心的人找到利用.不像谷歌身份验证器,手机丢失后验证码跟随手机走,在没有网络的时候也依旧显示,对用户信息资产造成严重威胁. 二次验证码官网(点击查看) 原文地址:https://

MVC学习系列——Model验证扩展

MVC中,实现了前端后端的验证. 前端验证.步骤: web.config这两个得开启: <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> JS设置 第一步:引入页面js @Scripts.Render("~/bundles/jque

7Python标准库系列之requests模块

Python标准库系列之requests模块 Requests is the only Non-GMO HTTP library for Python, safe for human consumption. 官方文档:http://docs.python-requests.org/en/master/ 安装Requests模块 Requests模块官方提供了两种方式安装: pip方式安装 pip install requests 源码方式安装 git clone git://github.co

标准库系列之xml模块

Python标准库系列之xml模块 Python's interfaces for processing XML are grouped in the xml package. 带分隔符的文件仅有两维的数据:行和列.如果你想在程序之间交换数据结构,需要一种方法把层次结构.序列.集合和其他的结构编码成文本. XML是最突出的处理这种转换的标记(markup)格式,它使用标签(tag)分个数据,如下面的实例文件menu.xml所示: <?xml version="1.0" encod

安装程序不能验证Update.inf文件的完整性,请确定加密服务正在此计算机上执行

近期安装Microsoft .NET Framework 4(独立安装程序)时,提示"安装程序不能验证Update.inf文件的完整性,请确定加密服务正在此计算机上执行" 没法放狗 方案一: 1.我的电脑"右键"管理"→打开"计算机管理"→   点击"服务",在服务管理器的主窗体服务列表中,找到名称为"Cryptographic Services"的服务项,双击该服务项, 在弹出的该服务项属性对话

[原创]java WEB学习笔记71:Struts2 学习之路-- struts2常见的内建验证程序及注意点,短路验证,非字段验证,错误消息的重用

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------