8

我有,比方說,這個簡單的類:驗證使用屬性

public class User 
{ 
    [Required(AllowEmptyStrings = false, ErrorMessage="EmailIsRequired"] 
    public string EmailAddress { get; set; } 
} 

我知道如何在System.ComponentModel.DataAnnotations命名空間中使用Validator.TryValidateProperty和Validator.TryValidateObject。爲了這個工作,你需要一個你想驗證的對象的實際實例。

但現在,我想驗證一個特定值,而用戶類的實例,如:

TryValidateValue(typeof(User), "EmailAddress", "[email protected]"); 

的目標是,我想測試之前,其實不必實例對象本身(的值原因是我只允許創建有效的域實體)。所以實際上我想在類而不是實例上使用驗證屬性。

任何想法如何做到這一點?

謝謝!

編輯:與此同時,我決定不使用數據註釋,而是使用http://fluentvalidation.codeplex.com,以便驗證移出實體。這種驗證可以從實體內部以及我的命令處理程序中觸發。由於流利的符號,驗證本身看起來更具可讀性。

+0

您剛纔說您正試圖避免實例化的域對象,如果它們是無效的,但究竟是將其實例化的影響?有可能你的對象做了太多事情,如果簡單地調用構造函數會搞砸什麼,你應該分解它的責任。 –

+0

域實體正在檢查其構造函數中的所有字段,如果其中任何一個未驗證,則拋出異常,因此無法創建該對象。但現在,在我的命令處理程序中,爲了進行上下文驗證,我需要驗證電子郵件地址,但我不需要該對象本身。所以我想知道:爲什麼我不能重用這個電子郵件驗證,而不需要此對象的實例。我也可以將驗證完全移出實體,但是我不能使用數據註釋,我猜... –

+0

有沒有辦法創建自定義派生註釋?然後,您可以共享註釋與此命令處理程序之間驗證的實現。這可能是一種黑客行爲,但我個人認爲註釋並不是一個完整或完全因素化的域約束驗證架構解決方案(它們無法處理跨屬性約束,如果應用於類,則不支持富邏輯),所以你只能用你所擁有的東西做最好的。 –

回答

16

這裏是你如何可以使用TryValidateValue方法的例子:

public class User 
{ 
    [Required(AllowEmptyStrings = false, ErrorMessage = "EmailIsRequired")] 
    public string EmailAddress { get; set; } 
} 

class Program 
{ 
    static void Main() 
    { 
     var value = "[email protected]"; 

     var context = new ValidationContext(value, null, null);   
     var results = new List<ValidationResult>(); 
     var attributes = typeof(User) 
      .GetProperty("EmailAddress") 
      .GetCustomAttributes(false) 
      .OfType<ValidationAttribute>() 
      .ToArray(); 

     if (!Validator.TryValidateValue(value, context, results, attributes)) 
     { 
      foreach (var result in results) 
      { 
       Console.WriteLine(result.ErrorMessage); 
      } 
     } 
     else 
     { 
      Console.WriteLine("{0} is valid", value); 
     } 
    } 
}