2009-11-18 62 views

回答

44

您可以使用DataAnnotations。Validator类,如下所述:

http://johan.driessen.se/archive/2009/11/18/testing-dataannotation-based-validation-in-asp.net-mvc.aspx

但如果您使用的是“伙伴”类的元数据,您需要注册这个事实你前对其进行验证,如下所述:

http://forums.silverlight.net/forums/p/149264/377212.aspx

TypeDescriptor.AddProviderTransparent(
    new AssociatedMetadataTypeTypeDescriptionProvider(typeof(myEntity), 
    typeof(myEntityMetadataClass)), 
    typeof(myEntity)); 

List<ValidationResult> results = new List<ValidationResult>(); 
ValidationContext context = new ValidationContext(myEntity, null, null) 
bool valid = Validator.TryValidateObject(myEntity, context, results, true); 

[增加了以下对摆振的评论作出回应]

我写了一个通用的方法以实现上述的逻辑,以使得任何对象都可以调用它:

// If the class to be validated does not have a separate metadata class, pass 
// the same type for both typeparams. 
public static bool IsValid<T, U>(this T obj, ref Dictionary<string, string> errors) 
{ 
    //If metadata class type has been passed in that's different from the class to be validated, register the association 
    if (typeof(T) != typeof(U)) 
    { 
     TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(T), typeof(U)), typeof(T)); 
    } 

    var validationContext = new ValidationContext(obj, null, null); 
    var validationResults = new List<ValidationResult>(); 
    Validator.TryValidateObject(obj, validationContext, validationResults, true); 

    if (validationResults.Count > 0 && errors == null) 
     errors = new Dictionary<string, string>(validationResults.Count); 

    foreach (var validationResult in validationResults) 
    { 
     errors.Add(validationResult.MemberNames.First(), validationResult.ErrorMessage); 
    } 

    if (validationResults.Count > 0) 
     return false; 
    else 
     return true; 
} 

在需要被验证的每个对象,我添加调用此方法:

[MetadataType(typeof(Employee.Metadata))] 
public partial class Employee 
{ 
    private sealed class Metadata 
    { 
     [DisplayName("Email")] 
     [Email(ErrorMessage = "Please enter a valid email address.")] 
     public string EmailAddress { get; set; } 
    } 

    public bool IsValid(ref Dictionary<string, string> errors) 
    { 
     return this.IsValid<Employee, Metadata>(ref errors); 
     //If the Employee class didn't have a buddy class, 
     //I'd just pass Employee twice: 
     //return this.IsValid<Employee, Employee>(ref errors); 
    } 
} 
+0

我有一个与MD相关的gazillion类,你对如何动态地将它与MD关联起来有什么好的想法,但是我想按需做,也就是说只有当我要使用这个类时(或者它的验证)和只有一次。 – Shimmy 2010-08-10 03:07:09

+0

@Shimmy - 见上文。 – 2010-10-13 17:04:29

+0

谢谢! 顺便说一句,不需要将字典标记为'ref',因为无论如何您都不会更改引用,只需访问其属性即可。 – Shimmy 2010-10-14 06:15:00

0

使用“好友类”。编号4在this how-to

+0

您提供的链接不适用于WPF,我想我在我的文章中提到过。 – Shimmy 2010-01-23 23:40:14

4

我认为Craigs答案中缺少的是如何实际检查是否存在验证错误。这是由史蒂夫·桑德森对于那些谁想要在输精管层,然后演示运行验证检查书面DataAnnotation验证亚军(http://blog.codeville.net/category/xval/,该代码是在示例项目):

public static IEnumerable<ErrorInfo> GetErrors(object instance) 
{ 
    var metadataAttrib = instance.GetType().GetCustomAttributes 
     (typeof(MetadataTypeAttribute), true). 
      OfType<MetadataTypeAttribute>().FirstOrDefault(); 
    var buddyClassOrModelClass = 
     metadataAttrib != null ? 
     metadataAttrib.MetadataClassType : 
     instance.GetType(); 
    var buddyClassProperties = TypeDescriptor.GetProperties 
     (buddyClassOrModelClass).Cast<PropertyDescriptor>(); 
    var modelClassProperties = TypeDescriptor.GetProperties 
     (instance.GetType()).Cast<PropertyDescriptor>(); 

    return from buddyProp in buddyClassProperties 
      join modelProp in modelClassProperties 
       on buddyProp.Name equals modelProp.Name 
      from attribute in buddyProp.Attributes. 
       OfType<ValidationAttribute>() 
      where !attribute.IsValid(modelProp.GetValue(instance)) 
      select new ErrorInfo(buddyProp.Name, 
       attribute.FormatErrorMessage(string.Empty), instance); 
} 

我不熟悉的WPF(不知道如果有问题的话可以使用一些现成的解决方案),但也许你可以使用它。

另外,他的博客上有一些评论,在某些情况下,它没有正确评估验证规则,但它从未失败过。

+0

在WPF中,必须根据属性更改来触发它。 – Shimmy 2010-07-22 04:39:06

+0

这是完成它的一个有趣的方式 - 我可以用这些想法修改我的版本(上面)。 – 2010-10-13 17:08:10