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

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

概述前情回顾:上一篇2) 验证器实现简单描述了下验证器的简单实现本文将说说Fluent方式的实现,欢迎大神们指点指点3) Fluent以及扩展方法实现我们按照之前 Fluent 的设想以及我们解耦的方式, 前情回顾:

上一篇 2) 验证器实现 简单描述了下验证器的简单实现

本文将说说Fluent方式的实现,欢迎大神们指点指点

 

3) Fluent以及扩展方法实现

我们按照之前 Fluent 的设想以及我们解耦的方式,所以我们先实现一个创建验证器创建者的静态类:

public static class ValIDation{	public static IValIDatorBuilder<T> NewValIDatorBuilder<T>()  // 创建验证器创建者	{		return Container.Resolve<IValIDatorBuilder<T>>();	}	public static ValIDateContext CreateContext(object valIDateObject,ValIDateOption option = ValIDateOption.StopOnFirstFailure,params string[] ruleSetList)  // 创建验证数据上下文参数	{		var result = Container.Resolve<ValIDateContext>();		result.Option = option;		result.RuleSetList = ruleSetList;		result.ValIDateObject = valIDateObject;		return result;	}}

 

我们接着实现 IValIDatorBuilder 

public class ValIDatorBuilder<T> : IValIDatorBuilder<T>{	public ObservableCollection<IValIDateRuleBuilder> Builders { get; set; }	public ValIDatorBuilder()	{		Builders = new ObservableCollection<IValIDateRuleBuilder>();	}	public IValIDator Build()	// 最终build 方法	{		var result = Container.Resolve<IValIDatorSetter>();		result.SetRules(Builders.Select(i => i.Build()));		return result;	}	public IFluentRuleBuilder<T,TProperty> RuleFor<TProperty>(Expression<Func<T,TProperty>> Expression)  // 验证规则创建者方法	{		ParamHelper.CheckParamNull(Expression,"Expression","Can't be null");		var builder = Container.Resolve<IRuleBuilder<T,TProperty>>();		builder.SetValueGetter(Expression);		Builders.Add(builder as IValIDateRuleBuilder);		return builder;	}	public voID RuleSet(string ruleSet,Action<IValIDatorBuilder<T>> action)   // 规则分组标志设置方法	{		ParamHelper.CheckParamEmptyOrNull(ruleSet,"ruleSet","Can't be null");		ParamHelper.CheckParamNull(action,"action","Can't be null");		var upRuleSet = ruleSet.toupper();		var updateRuleSet = new NotifyCollectionChangedEventHandler<IValIDateRuleBuilder>((o,e) =>		{			if (e.Action != NotifyCollectionChangedAction.Add) return;			foreach (var item in e.NewItems)			{				item.RuleSet = upRuleSet;			}		});		Builders.CollectionChanged += updateRuleSet;		action(this);		Builders.CollectionChanged -= updateRuleSet;	}	    // 规则分组标志设置方法这样实现可以简化设置的格式,让代码更清晰    // 比如    //	      var builder = ValIDation.NewValIDatorBuilder<Student>();    //        builder.RuleSet("A",b =>    //        {    //            b.RuleFor(i => i.name).NotNull()    //                    .Must(i=>i.Length > 10)    //                    .OverrIDename("student name")    //                    .OverrIDeError("no name")    //              .ThenRuleFor(i => i.Age)    //                    .Must(i => i >= 0 && i <= 18)    //                    .OverrIDename("student age")    //                    .OverrIDeError("not student");    //        });}

  

接着我们实现 IRuleBuilder:

public class RuleBuilder<T,TValue> : IRuleBuilder<T,TValue>{	public string RuleSet { get; set; }	public Func<object,TValue> ValueGetter { get; protected set; }	public Expression<Func<T,TValue>> ValueExpression { get; protected set; }	public string Valuename { get; set; }	public string Error { get; set; }	public IValIDateRuleBuilder NextRuleBuilder { get; set; }	public Func<ValIDateContext,bool> Condition { get; set; }	public Func<ValIDateContext,string,IValIDateResult> ValIDateFunc { get; set; }	public voID SetValueGetter(Expression<Func<T,TValue>> Expression)  // 设置获取值的方法	{		ValueExpression = Expression;		var stack = new Stack<MemberInfo>();		var memberExp = Expression.Body as MemberExpression;		while (memberExp != null)		{			stack.Push(memberExp.Member);			memberExp = memberExp.Expression as MemberExpression;		}		var p = Expression.Parameter(typeof(object),"p");		var convert = Expression.Convert(p,typeof(T));		Expression exp = convert;		if (stack.Count > 0)		{			while (stack.Count > 0)			{				exp = Expression.MakeMemberAccess(exp,stack.Pop());			}			Valuename = exp.ToString().Replace(convert.ToString() + ".","");  // 设置默认的属性名		}		else		{			Valuename = string.Empty;		}		ValueGetter = Expression.Lambda<Func<object,TValue>>(exp,p).Compile(); // 用表达式生成动态获取不同对象的值的方法	}	public IFluentRuleBuilder<T,TProperty> ThenRuleFor<TProperty>(Expression<Func<T,TProperty>> Expression) // 创建子级规则接口方法	{		var builder = Utils.RuleFor(Expression);		NextRuleBuilder = builder as IValIDateRuleBuilder;		return builder;	}	public IValIDateRule Build() // 规则创建方法	{		var rule = Container.Resolve<IValIDateRule>();		rule.Valuename = Valuename;		rule.Error = Error;		rule.ValIDateFunc = ValIDateFunc;		rule.Condition = Condition;		rule.RuleSet = RuleSet;		var nextBuilder = NextRuleBuilder;		if (nextBuilder != null)			rule.NextRule = nextBuilder.Build();		return rule;	}}

  

貌似我们完成了大部分了,但是好像哪里不对,

回忆一下,好像这个持有如何验证逻辑方法的属性没有相关代码处理

public class ValIDateRule : IValIDateRule{	public Func<ValIDateContext,IValIDateResult> ValIDateFunc { get; set; }}

好吧,我们来建立一个基类先:

public abstract class BaseChecker<T,TProperty>{	public virtual IRuleMessageBuilder<T,TProperty> SetValIDate(IFluentRuleBuilder<T,TProperty> builder) // 设置验证规则逻辑方法	{		ParamHelper.CheckParamNull(builder,"builder","Can't be null");		var build = builder as IRuleBuilder<T,TProperty>;		build.ValIDateFunc = (context,name,error) =>		{			var value = build.ValueGetter(context.ValIDateObject);			var result = Container.Resolve<IValIDateResult>();			return ValIDate(result,value,error);		};		return build as IRuleMessageBuilder<T,TProperty>;	}	public IValIDateResult GetResult()        // 获取验证结果实例对象	{		return Container.Resolve<IValIDateResult>();	}	public voID AddFailure(IValIDateResult result,string name,object value,string error) // 添加错误信息	{		result.Failures.Add(new ValIDateFailure()		{			name = name,Value = value,Error = error		});	}	public abstract IValIDateResult ValIDate(IValIDateResult result,TProperty value,string error); // 验证规则逻辑接口}

  

再接着我们实现一个Must check 类:

public class MustChecker<T,TProperty> : BaseChecker<T,TProperty>{	private Func<TProperty,bool> m_MustBeTrue;	public MustChecker(Func<TProperty,bool> func)	{		ParamHelper.CheckParamNull(func,"func","Can't be null");		m_MustBeTrue = func;	}	public overrIDe IValIDateResult ValIDate(IValIDateResult result,string error)	{		if (!m_MustBeTrue(value))		{			AddFailure(result,error);		}		return result;	}}

  

然后我们接口绑定加上:

public static class Container{	public static IlifetimeScope CurrentScope { get; set; }	public static voID Init(Action<ContainerBuilder> action)	{		ParamHelper.CheckParamNull(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.RegisterGeneric(typeof(RuleBuilder<,>)).As(typeof(IRuleBuilder<,>)).InstancePerDependency();			builder.Register(c => new ValIDateContext() { RuleSelector = c.Resolve<IRuleSelector>() });			builder.RegisterType<ValIDateRule>().As<IValIDateRule>().InstancePerDependency();			builder.RegisterType<ValIDateResult>().As<IValIDateResult>().InstancePerDependency();			builder.RegisterGeneric(typeof(ValIDatorBuilder<>)).As(typeof(IValIDatorBuilder<>)).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>();	}}

  

再然后我们添加 must 的扩展方法:

public static class Syntax{	public static IRuleMessageBuilder<T,TProperty> Must<T,TProperty>(this IFluentRuleBuilder<T,TProperty> builder,Func<TProperty,bool> func)	{		return new MustChecker<T,TProperty>(func).SetValIDate(builder);	}}

  

我们再添加一些消息设置相关的扩展方法:

public static class Syntax{	....	public static IRuleMessageBuilder<T,TProperty> When<T,TProperty>(this IRuleMessageBuilder<T,"Can't be null");		var ruleBuilder = builder as IRuleBuilder<T,TProperty>;		ruleBuilder.Condition = (context) =>		{			var value = ruleBuilder.ValueGetter(context.ValIDateObject);			return func(value);		};		return builder;	}	public static IRuleMessageBuilder<T,TProperty> OverrIDename<T,string name)	{		(builder as IValIDateRuleBuilder).Valuename = name;		return builder;	}	public static IRuleMessageBuilder<T,TProperty> OverrIDeError<T,string error)	{		(builder as IValIDateRuleBuilder).Error = error;		return builder;	}}

  

大功告成,我们现在就可以这样使用了:

Container.Init();var builder = ValIDation.NewValIDatorBuilder<Student>();builder.RuleSet("A",b =>{	b.RuleFor(i => i.name).Must(i=>i.Length > 10)			.OverrIDename("student name")			.OverrIDeError("no name")	  .ThenRuleFor(i => i.Age)			.Must(i => i >= 0 && i <= 18)			.OverrIDename("student age")			.OverrIDeError("not student");});var v = builder.Build();var student = new BigStudent() { Age = 13,name = "v" };var context = ValIDation.CreateContext(student);var result = v.ValIDate(context);Assert.IsNotNull(result);Assert.True(result.IsValID);Assert.True(result.Failures.Count == 0);

  

最后代码和dll可以通过如下方法获取:

nuget:https://www.nuget.org/packages/ObjectValidator/

github:https://github.com/fs7744/ObjectValidator

 

PS: 大神们快快给我些批评吧,冰天雪地跪求了

总结

以上是内存溢出为你收集整理的实现一个对象验证库系列 -- 3) Fluent以及扩展方法实现 (请大神批评)全部内容,希望文章能够帮你解决实现一个对象验证库系列 -- 3) Fluent以及扩展方法实现 (请大神批评)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1213360.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存