0

假设我有几个字段的实体。有些字段在某些特定状态下是必需的,而其他字段仅在进一步/其他状态下是必需的。

public class Entity
{
    //Required always
    public SomeReference {}

    //Required in specific situation/scenario
    public OtherReference {}
}

如何使用一些已知的验证框架来实现该场景,或者如何自己完成?

求助:Udi Dahan 对此有一些想法。 http://www.udidahan.com/2007/04/30/generic-validation/

4

2 回答 2

1

我有一个我目前正在使用的解决方案。我使用Fluent 验证,但我仍然习惯它。我可以给你一个我有的简单场景的例子。也许它有帮助。我有一个用户类,具有地址对象属性。在某些时候,我只想验证用户详细信息(姓名、电子邮件、密码等),而在另一个状态下,我想验证用户地址(第一行、邮政编码等)。

类看起来像这样:

public class User {
    public virtual string Name { get; set; }
    public virtual string Email { get; set; }
    public virtual string Password { get; set; }
    public virtual Address Address { get; set; }        
}

public class Address {
    public virtual string Address1 { get; set; }
    public virtual string PostCode { get; set; }
}

然后我有两个(简化的)验证器,一个用于地址,一个用于用户:

    public AddressValidator() {
        RuleFor(address => address.Address1)
            .NotNull()
            .WithMessage("Please enter the first line of your address");

        RuleFor(address => address.PostCode)
            .NotNull()
            .WithMessage("Please enter your postcode")
            .Matches(UK_POSTCODE_REGEX)
            .WithMessage("Please enter a valid post code!");
    }

    public UserValidator() {
        RuleFor(user => user.FirstName)
            .NotNull()
            .WithMessage("Please provide a first name")
            .Length(3, 50)
            .WithMessage("First name too short");

        RuleFor(user=> user.Password)
            .Length(8, 50)
            .WithMessage("Password is too short");
    }

然后我创建一个模型验证器,例如,假设我们有一个用户输入地址的表单,我们创建一个 AddressModelValidator,并且可以重用我们编写的验证器:

    public AddressModelValidator()  {
        RuleFor(user => user.id)
            .NotNull()
            .WithMessage("An error has occured, please go back and try again");

        RuleFor(user => user.Address).SetValidator(new AddressValidator());
    }

因此,经过一番思考,您确实可以创建一些不错的模型,并减少验证代码的重复!

于 2009-12-21T10:24:07.313 回答
0

我的首选是将常见的验证功能(例如电子邮件和日期验证)本地化到一个 ValidationService 类中,我可以将我的对象传递到该类中。对于其余部分,尽管我倾向于将验证放入课程本身。如果我使用 LINQ to SQL,那么我可以在我的对象上创建一个 Validate() 方法,LINQ to SQL 将在将对象保存到数据库之前调用该方法,如下所示:

public void Validate()
{
    if(!IsValid)
        throw new ValidationException("Rule violations prevent saving");
}

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

public IEnumerable<RuleViolation> GetRuleViolations()
{
    if(this.TermID == 0)
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(1), "agreeWithTerms");

    if(ValidationService.ValidateDate(this.Birthdate.ToString()))
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(2), "birthDate");

    if (!(Username.Length >= ConfigurationService.GetMinimumUsernameLength()) ||
        !(Username.Length <= ConfigurationService.GetMaximumUsernameLength()))
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(5), "username");

    if(ValidationService.ValidateUsernameComplexity(Username))
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(6), "username");

    if (AccountID == 0 && ObjectFactory.GetInstance<IAccountRepository>().UsernameExists(this.Username))
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(7), "username");

    if (!ValidationService.ValidateEmail(Email))
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(8), "email");

    if (AccountID == 0 && ObjectFactory.GetInstance<IAccountRepository>().EmailExists(this.Email))
        yield return new RuleViolation(HelpMessageService.GetHelpMessageBodyByID(9), "email");

    yield break;
}

阅读此处以全面了解这一点:http: //nerddinnerbook.s3.amazonaws.com/Part3.htm

于 2009-06-22T20:19:50.333 回答