回到目錄 在MVC,EF,LINQ環境里,我們經常會用到DataModel(DO)和ViewModel(VO),可能對於它們的屬性校驗我們會採用特性的方式,當然這很直觀,就連微軟的DEMO也是如些,一般是這樣的代碼 而這種設計方式給我們以後的維護帶來很多問題,具體大叔總結一下: 綜上所述,Fluen ...
在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等書籍!
感謝各位的閱讀!