告诉我有关我的实体验证的愚蠢(以及如何改进它)

时间:2009-10-07 22:22:21

标签: design-patterns tdd domain-driven-design bdd

我有一个实现接口的IEntity接口,IValidatable

public interface IValidatable {
    bool IsValid { get; }
    bool IsValidForPersistence { get; }
    // Rules applied at UI time (please enter your name, etc)
    IEnumerable<RuleViolation> GetRuleViolations();
    // Rules to be applied only at persistence time
    IEnumerable<RuleViolation> GetPersistenceRuleViolations();
}

public interface IEntity : IValidatable {
    int ID { get; set; }
}

为方便起见,我实现了我的Entity类:

 public abstract class Entity : IEntity {

        public virtual int ID { get; set; }

        public virtual bool IsValid {
            get { return RuleViolations().Count() == 0; }
        }

        public virtual bool IsValidForPersistence {
            get { return PersistenceRuleViolations().Count() == 0; }
        }

        public virtual IEnumerable<RuleViolation> GetRuleViolations() {
            return new List<RuleViolation>();
        }

        public virtual IEnumerable<RuleViolation> GetPersistenceRuleViolations() {
            return new List<RuleViolation>();
        }
    }

默认情况下,实体有效,直到覆盖GetRuleViolations()或GetPersistenceRuleViolations()为止。

  public partial class Company {

      public override IEnumerable<RuleViolation> GetRuleViolations() {
         if (String.IsNullOrEmpty(CompanyName))
                yield return new RuleViolation("CompanyName", "Name is required.");
     }

      public override IEnumerable<RuleViolation> GetPersistenceRuleViolations() {
         // Include standard rules too
         foreach (RuleViolation rule in RuleViolations) {
              yield return rule;
          }
        // Check some data based on a referenced entity "Bid"
        if (!Active && Bid.Active)
            yield return new RuleViolation("Active", 
               "When Active is set to false, the Bid must also be inactive.");
     }
  }

我知道这对于验证来说有点天真,所以除了任何拼写错误之外,还有什么可以改进的?

3 个答案:

答案 0 :(得分:1)

我建议查看具有良好业务规则和验证基础框架的NCommon框架,或者xVal验证框架,它还支持来自同一规则集的客户端验证。

答案 1 :(得分:1)

请记住,如果您从另一个实体派生实体,例如。来自Person的客户,您需要一个foeach来获取基类违规行为:

  public override IEnumerable<RuleViolation> GetRuleViolations() 
  {
     // inherit base class valiations
     foreach (var violation in base.GetRuleViolations())
     {
         yield return violation;
     }

     // add own validations
     if (String.IsNullOrEmpty(CompanyName))
         yield return new RuleViolation("CompanyName", "Name is required.");
  }

哪个不太好。

就个人而言,我也会寻找现有的东西,因为验证是一个普遍的问题,并且已经有很多解决方案。

答案 2 :(得分:0)

我正在使用ASP.NET MVC并使用Data Annotation Validators执行类似操作。我从ValidationAttribute继承并覆盖FormatErrorMessage,以便我可以集体返回错误。