2

custom がValidationAttributeありますが、CheckBox がチェックされている場合にのみ、このプロパティを検証したいと考えています。

クラスを から継承しIValidationObject、そのValidateメソッドを使用してカスタム検証を実行していますがValidationAttribute、コードを複製する代わりにここでカスタムを使用できますか? もしそうなら、どのように?

public class MyClass : IValidatableObject
{
    public bool IsReminderChecked { get; set; }
    public bool EmailAddress { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (IsReminderChecked)
        {
            // How can I validate the EmailAddress field using
            // the Custom Validation Attribute found below?
        }
    }
}


// Custom Validation Attribute - used in more than one place
public class EmailValidationAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        var email = value as string;

        if (string.IsNullOrEmpty(email))
            return false;

        try
        {
            var testEmail = new MailAddress(email).Address;
        }
        catch (FormatException)
        {
            return false;
        }

        return true;
    }
}
4

1 に答える 1

6

別のプロパティの値に基づいてプロパティを検証することは可能ですが、検証エンジンが期待どおりに機能することを確認するには、いくつかの手順を踏む必要があります。Simon Ince のRequiredIfAttributeには優れたアプローチがあり、メソッドValidateEmailIfAttributeに電子メールの検証ロジックを追加するだけで簡単に変更できるはずです。IsValid

たとえば、今と同じように、基本検証属性を使用できます。

public class ValidateEmailAttribute : ValidationAttribute
{
  ...
}

次に、Ince のアプローチを使用して、条件付きバージョンを定義します。

public class ValidateEmailIfAttribute : ValidationAttribute, IClientValidatable
{
  private ValidateEmailAttribute _innerAttribute = new ValidateEmailAttribute();

  public string DependentProperty { get; set; }
  public object TargetValue { get; set; }

  public ValidateEmailIfAttribute(string dependentProperty, object targetValue)
  {
    this.DependentProperty = dependentProperty;
    this.TargetValue = targetValue;
  }

  protected override ValidationResult IsValid(object value, ValidationContext validationContext)
  {
    // get a reference to the property this validation depends upon
    var containerType = validationContext.ObjectInstance.GetType();
    var field = containerType.GetProperty(this.DependentProperty);

    if (field != null)
    {
      // get the value of the dependent property
      var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);

      // compare the value against the target value
      if ((dependentvalue == null && this.TargetValue == null) ||
          (dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
      {
        // match => means we should try validating this field
        if (!_innerAttribute.IsValid(value))
          // validation failed - return an error
          return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
      }
    }

    return ValidationResult.Success;
  }

  // Client-side validation code omitted for brevity
}

次に、次のようなものを使用できます。

[ValidateEmailIf("IsReminderChecked", true)]
public bool EmailAddress { get; set; }
于 2012-06-20T15:35:20.043 に答える