回到目录

在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; }

而这种设计方式给我们以后的维护带来很多问题,具体大叔总结一下:

  1. 与数据实体混在一起,不利用扩展,更新实体你加的特性可能会丢失

  2. 如果有多个VO,那么你需要把它加到具体的VO上,因为DO的语义可能不太明确

  3. 不方便迁移,它与ModelState耦合太高

  4. 从面向对象的角度来看,它的职责太单一,引起变因太多

综上所述,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( ValidatorDecorator<CreateUserEvent>( UserEventHandler(),   BusManager.Instance.Subscribe( LoggerDecorator<CreateUserEvent>( CreateUserEvent { UserName =  });

装饰器要求你转一个要被装饰的对象和一个装饰器,就可以了。

    /// <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等书籍!

感谢各位的阅读!

更多相关文章

  1. XML 实体引用、注释、命名规则
  2. 深入理解XML中的字符实体与字符数据
  3. XML入门教程-实体的具体介绍
  4. XML实体扩展攻击代码实例分享
  5. 用C#实现XML和实体类之间序列化和反序列化相互转换
  6. 太扎心了!外包程序员的真实体验
  7. 数据库界的 Swagger,一键自动生成 Java 实体类和数据库文档!不讲武
  8. Mvc 5和实体框架6中的Jquery多文件上载问题
  9. 使用hibernate和vraptor通过POST插入带有外键的实体

随机推荐

  1. Android(安卓)应用初始化及窗体事件的分
  2. xUtils3.3.x注解使用实例
  3. Android 中比 Timer 更好方法
  4. Android中自动跳转到系统设置界面
  5. cmd>>android
  6. Android ListView强制停止滚动
  7. Android 仿3g体育门户客户端赛事图标浮出
  8. Android菜鸟日记14-对话框
  9. 【android】WebView缓存资料收集
  10. Android布局优化(一),Android渲染机制