2011-10-05 30 views
42

Tôi có một đồ thị đối tượng rải rác với các thuộc tính DataAnnotation, trong đó một số thuộc tính của các đối tượng là các lớp mà chúng có thuộc tính xác nhận, vv.DataAnnotations: Recursively xác nhận toàn bộ đồ thị đối tượng

Trong các tình huống sau:

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; } 
} 

Nếu tôi cố gắng để xác nhận một Employee 's Address không có giá trị cho PostalCode, sau đó tôi muốn (và mong muốn) một ngoại lệ, nhưng tôi nhận được không. Đây là cách tôi đang làm nó:

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)); 

Những tùy chọn khác để tôi có với Validator đó sẽ đảm bảo tất cả các thuộc tính được xác nhận đệ quy?

Rất cám ơn trước.

Trả lời

47

câu trả lời của tôi đã quá lâu để đặt ở đây, vì vậy tôi biến nó thành một bài đăng blog :)

Recursive Validation Using DataAnnotations

Các giải pháp mang đến cho bạn một cách để đạt được xác nhận đệ quy bằng cách sử dụng phương pháp cơ bản mà bạn đang sử dụng hiện nay.

+1

+ 1 cho giải pháp tốt – Jehof

+0

Tốt, nhưng còn về bộ sưu tập thì sao? Thật tuyệt vời khi có khả năng xác thực các thuộc tính như 'địa chỉ ILI công khai

' này. Dù sao, cảm ơn cho giải pháp. – altso

+0

Thuộc tính không được đánh giá cho tôi. –

23

Đây là phương án thay thế cho cách tiếp cận thuộc tính chọn tham gia. Tôi tin rằng điều này sẽ đi qua các đồ thị đối tượng đúng và xác nhận tất cả mọi thứ.

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; 
} 

Hầu hết các up-to-date mã: https://github.com/reustmd/DataAnnotationsValidatorRecursive

gói: https://www.nuget.org/packages/DataAnnotationsValidator/

Ngoài ra, tôi đã cập nhật giải pháp này để xử lý đồ thị đối tượng theo chu kỳ. Cảm ơn vì bạn đã phản hồi.

+6

Tôi thích giải pháp này, nhưng hãy cẩn thận của vòng vô hạn khi đồ thị đối tượng có chu kỳ. –

+0

@ manu08 .... đồng bằng tuyệt vời - cảm ơn vì đã tiết kiệm thời gian. – Pakk

+0

Mẫu mã ở trên có một số vấn đề so với phiên bản git - do đó chắc chắn [theo liên kết] (https://github.com/reustmd/DataAnnotationsValidatorRecursive/tree/master/DataAnnotationsValidator/DataAnnotationsValidator) nếu bạn đang muốn triển khai này (hoặc 'Gói dữ liệu gói_thông báo gói dữ liệu' qua [nuget] (https://www.nuget.org/packages/DataAnnotationsValidator/)!) – rogersillito

Các vấn đề liên quan