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