EF架构~FluentValidation实体检验与实体分离了
在MVC,EF,LINQ环境里,我们经常会用到DataModel(DO)和ViewModel(VO),可能对于它们的属性校验我们会采用特性的方式,当然这很直观,就连微软的DEMO也是如些,一般是这样的代码
/// <summary> /// 机构ID /// </summary> [DisplayName("机构ID")] public int AgentId { get; set; } /// <summary> /// 机构名称 /// </summary> [DisplayName("机构名称")] [MaxLength(128)] public string AgentName { get; set; } /// <summary> /// 机构负责人 /// </summary> [DisplayName("机构负责人")] [MaxLength(128)] public string AgentUser { get; set; }
而这种设计方式给我们以后的维护带来很多问题,具体大叔总结一下:
- 与数据实体混在一起,不利用扩展,更新实体你加的特性可能会丢失
- 如果有多个VO,那么你需要把它加到具体的VO上,因为DO的语义可能不太明确
- 不方便迁移,它与ModelState耦合太高
- 从面向对象的角度来看,它的职责太单一,引起变因太多
综上所述,FluentValidation就诞生了!
nuget上去安装它:install-package FluentValidation
你的一个实体类,可以添加多个检验类,这相当于可以有多种检验类去装饰一个实体类,我觉得挺好!
public class CreateUserEventValidator : AbstractValidator<CreateUserEvent> { public CreateUserEventValidator() { RuleFor(command => command.UserName).NotEmpty().Length(5, 20).WithMessage("用户名升序为5-20字符!"); RuleFor(command => command.Email).NotEmpty().EmailAddress().WithMessage("不是有效的Email!"); RuleFor(command => command.BirthDay).NotEmpty().Must(i => i < DateTime.Now).WithMessage("你的年紀太小了!"); } }
使用时,可以通过IsValid,Errors等属性拿到你需要的信息,当然,你也可以把它在命令事件,领域事件上用一下,比如做个验证的装饰器,哪些处理程序要用校验,就通过这个装饰器装饰一下就行了,挺优雅!
//验证-装饰器 BusManager.Instance.Subscribe(new ValidatorDecorator<CreateUserEvent>(
new UserEventHandler(),
new CreateUserEventValidator())); //日志-装饰器 BusManager.Instance.Subscribe(new LoggerDecorator<CreateUserEvent>(new UserEventHandler())); BusManager.Instance.Publish(new CreateUserEvent { UserName = "占占大师5个字" });
装饰器要求你转一个要被装饰的对象和一个装饰器,就可以了。
/// <summary> /// 验证装饰器 /// </summary> /// <typeparam name="TEvent"></typeparam> [Serializable] public class ValidatorDecorator<TEvent> : IBusHandler<TEvent> where TEvent : IBusData { /// <summary> /// 要被装饰的处理程序 /// </summary> private readonly IBusHandler<TEvent> _inner; /// <summary> /// 校验装饰器集合 /// </summary> private readonly IValidator<TEvent>[] _validators; /// <summary> /// 初始化 /// </summary> /// <param name="inner">要被装饰的处理程序</param> /// <param name="validators">装饰器</param> public ValidatorDecorator(IBusHandler<TEvent> inner, params IValidator<TEvent>[] validators) { _inner = inner; _validators = validators; } public void Handle(TEvent evt) { var failures = _validators .Select(v => v.Validate(evt)) .SelectMany(result => result.Errors) .Where(error => error != null) .ToList(); if (failures.Any()) { throw new ValidationException("实体校验失败", failures); } _inner.Handle(evt); } }
对于一种知识的学习与理解是需要一些理论基础的,大家可以多看看设计模块,算法导论,.netCLR等书籍!
感谢各位的阅读!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2016-06-01 WebApi系列~StringContent参数需要添加MetaType对象
2016-06-01 DotNetCore跨平台~性能测试~可以放心使用了
2015-06-01 MongoDB学习笔记~自己封装的Curd操作(查询集合对象属性,更新集合对象)
2012-06-01 事件之道~一 如何让实体发生更新时,同时记录它更新的内容到日志表
2011-06-01 项目中的通用查询参数类,它体现了项目架构的大局观
2011-06-01 MVC模式中,如何使用AJAX进行分页