DataAnnotation属性が散在しているオブジェクトグラフがあります。オブジェクトの一部のプロパティは、それ自体が検証属性を持つクラスなどです。
次のシナリオでは:
public class Employee
{
[Required]
public string Name { get; set; }
[Required]
public Address Address { get; set; }
}
public class Address
{
[Required]
public string Line1 { get; set; }
public string Line2 { get; set; }
[Required]
public string Town { get; set; }
[Required]
public string PostalCode { get; set; }
}
Employee
の値を指定せずにAddress
のPostalCode
を検証しようとすると、例外が欲しい(そして期待される)が、何も得られない。以下がその方法です。
var employee = new Employee
{
Name = "Neil Barnwell",
Address = new Address
{
Line1 = "My Road",
Town = "My Town",
PostalCode = "" // <- INVALID!
}
};
Validator.ValidateObject(employee, new ValidationContext(employee, null, null));
すべてのプロパティが検証されることを保証するValidator
には、他にどのようなオプションがありますか再帰的に?
事前に感謝します。
私の答えはここに入れるには長すぎたので、ブログの投稿に変えました:)
このソリューションは、現在使用しているのと同じ基本的な方法を使用して、再帰的な検証を実現する方法を提供します。
オプトイン属性アプローチの代替手段を次に示します。これはオブジェクトグラフを適切にトラバースし、すべてを検証すると信じています。
public bool TryValidateObjectRecursive<T>(T obj, List<ValidationResult> results) {
bool result = TryValidateObject(obj, results);
var properties = obj.GetType().GetProperties().Where(prop => prop.CanRead
&& !prop.GetCustomAttributes(typeof(SkipRecursiveValidation), false).Any()
&& prop.GetIndexParameters().Length == 0).ToList();
foreach (var property in properties)
{
if (property.PropertyType == typeof(string) || property.PropertyType.IsValueType) continue;
var value = obj.GetPropertyValue(property.Name);
if (value == null) continue;
var asEnumerable = value as IEnumerable;
if (asEnumerable != null)
{
foreach (var enumObj in asEnumerable)
{
var nestedResults = new List<ValidationResult>();
if (!TryValidateObjectRecursive(enumObj, nestedResults))
{
result = false;
foreach (var validationResult in nestedResults)
{
PropertyInfo property1 = property;
results.Add(new ValidationResult(validationResult.ErrorMessage, validationResult.MemberNames.Select(x => property1.Name + '.' + x)));
}
};
}
}
else
{
var nestedResults = new List<ValidationResult>();
if (!TryValidateObjectRecursive(value, nestedResults))
{
result = false;
foreach (var validationResult in nestedResults)
{
PropertyInfo property1 = property;
results.Add(new ValidationResult(validationResult.ErrorMessage, validationResult.MemberNames.Select(x => property1.Name + '.' + x)));
}
}
}
}
return result;
}
最新のコード: https://github.com/reustmd/DataAnnotationsValidatorRecursive
パッケージ: https://www.nuget.org/packages/DataAnnotationsValidator/
また、このソリューションを更新して、循環オブジェクトグラフを処理しました。フィードバックをお寄せいただきありがとうございます。