2009-11-18 48 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