2009-11-18 7 views

Antwort

44

Sie können die DataAnnotations verwenden.Validator-Klasse, wie hier beschrieben:

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

Aber wenn man einen „Buddy“ Klasse für die Metadaten verwenden, müssen Sie diese Tatsache registrieren, bevor Sie bestätigen, wie hier beschrieben:

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

[Hinzugefügt folgende Shimmy Kommentar antworten]

Ich schrieb eine generische Methode, die Logik oben zu implementieren, so dass jedes Objekt so nennen kann:

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

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

In jedem Objekt, das validiert werden muss, ich einen Aufruf dieser Methode hinzufügen

+0

Ich habe eine gazillion Klassen im Zusammenhang mit MD, haben Sie eine gute Idee, wie Sie es mit der MD dynamisch verknüpfen, aber ich möchte es auf Nachfrage zu tun, dh nur wenn ich diese Klasse (oder Validierung) verwenden und nur einmal. – Shimmy

+0

@Shimmy - siehe oben. –

+0

danke! BTW, keine Notwendigkeit, das Wörterbuch als 'ref' zu markieren, da Sie die Referenz sowieso nicht ändern werden, greifen Sie einfach auf seine Eigenschaften zu. – Shimmy

0

Verwenden Sie eine "Buddy-Klasse". Nummer 4 in this how-to.

+0

Der Link zur Verfügung gestellt ist nicht in WPF, ich glaube, ich erwähnte das in meinem Beitrag. – Shimmy

4

Ich denke, dass was von Craigs Antwort fehlt ist, wie man tatsächlich überprüft, ob es Validierungsfehler gibt. Dies ist DataAnnotation Validierung Läufer von Steve Sanderson für diejenigen geschrieben, die Validierungsprüfung in deferent Schicht dann Präsentation ausgeführt werden sollen (http://blog.codeville.net/category/xval/, ist der Code in Beispielprojekt):

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

ich mit WPF nicht vertraut bin (nicht sicher, wenn es eine Out-of-the-Box-Lösung für Ihre Frage gibt), aber vielleicht können Sie sie verwenden.

Es gibt auch einige Kommentare in seinem Blog, die in einigen Fällen Validierungsregel nicht richtig bewerten, aber es ist nie für mich gescheitert.

+0

In WPF muss es pro Eigenschaftsänderung ausgelöst werden. – Shimmy

+0

Dies ist ein interessanter Weg, um es zu erreichen - ich kann meine Version (oben) mit einigen dieser Ideen überarbeiten. –

3

Sie könnten in der Booklibrary Beispielanwendung des WPF Application Framework (WAF) interessiert. Es erfüllt genau das, wonach Sie fragen: Verwenden von DataAnnotations in WPF & Entity Framework.