文章出處

回到目錄

在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(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等書籍!

感謝各位的閱讀!

回到目錄

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()