カスタム検証属性を書くことができます:
public class PhoneAttribute : ValidationAttribute
{
private readonly string _phoneTypeProperty;
public PhoneAttribute(string phoneTyperoperty)
{
_phoneTypeProperty = phoneTyperoperty;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var property = validationContext.ObjectType.GetProperty(_phoneTypeProperty);
if (property == null)
{
return new ValidationResult(string.Format("Unknown property: {0}", _phoneTypeProperty));
}
var phone = Convert.ToString(value, CultureInfo.CurrentCulture);
if (string.IsNullOrEmpty(phone))
{
return null;
}
var phoneType = (long)property.GetValue(validationContext.ObjectInstance, null);
Regex regex = null;
if (phoneType == 1)
{
regex = new Regex(@"^08[589][0-9]{8}$");
}
else if (phoneType == 2)
{
regex = new Regex("^[1-9][0-9]{9}$");
}
else
{
return new ValidationResult(string.Format("Unknown phone type: {0}", phoneType));
}
var match = regex.Match(phone);
if (match.Success && match.Index == 0 && match.Length == phone.Length)
{
return null;
}
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
次に、ビュー モデル プロパティを次の属性で装飾します。
public class MyViewModel
{
[Phone("PhoneType", ErrorMessage = "Invalid Number!")]
public string Phone { get; set; }
public long PhoneType { get; set; }
}
検証で生活を楽にしたい場合の別の可能性 (強くお勧めします) は、FluentValidation.NETを使用することです。何行もの配管コードを記述して、どの部分が配管で、どの部分が実際の検証であるかを理解できなくなる代わりに、検証ルールを定義する方がいかに簡単かを見てください。FluentValidation.NET では配管はありません。検証要件を流暢に表現します。
public class MyViewModelValidator : AbstractValidator<MyViewModel>
{
public MyViewModelValidator()
{
RuleFor(x => x.Phone)
.Matches(@"^08[589][0-9]{8}$").When(x => x.PhoneType == 1)
.Matches("^[1-9][0-9]{9}$").When(x => x.PhoneType == 2);
}
}
このバリデーターを前のものと比較するだけです。