2013-06-24 5 views
7

Esiste un modo in .NET Framework per assegnare un metodo o un validatore a un'istanza di oggetto la cui classe è decorata con Data Annotations e ricevere una raccolta di errori?Come si fa la convalida della proprietà di una classe C# utilizzando le annotazioni di dati in .NET Framework 3.5?

Vedo che c'è a way to do this in .NET 4.x. Ma esiste un meccanismo simile in .NET 3.5?

+2

non so se c'è qualcosa di simile in .NET 3.5, ma se siete disposti a utilizzare un'altra libreria, Enterprise Application Block di Microsoft contiene una Validation Application Block che contiene un validatore classe che può validare oggetti decorati con DataAnnotations. –

risposta

10

Con un po 'di riflessione, è possibile creare il proprio validatore che esegue la scansione del ValidationAttributes sulle proprietà che avete. Potrebbe non essere una soluzione perfetta, ma se si è limitati a utilizzare .NET 3.5, questa sembra una soluzione leggera, si spera che si ottenga l'immagine.

static void Main(string[] args) 
{ 

    Person p = new Person(); 
    p.Age = 4; 

    var results = Validator.Validate(p); 

    results.ToList().ForEach(error => Console.WriteLine(error)); 

    Console.Read(); 
}  

// Simple Validator class 
public static class Validator 
{ 
    // This could return a ValidationResult object etc 
    public static IEnumerable<string> Validate(object o) 
    { 
     Type type = o.GetType(); 
     PropertyInfo[] properties = type.GetProperties(); 
     Type attrType = typeof (ValidationAttribute); 

     foreach (var propertyInfo in properties) 
     { 
      object[] customAttributes = propertyInfo.GetCustomAttributes(attrType, inherit: true); 

      foreach (var customAttribute in customAttributes) 
      { 
       var validationAttribute = (ValidationAttribute)customAttribute; 

       bool isValid = validationAttribute.IsValid(propertyInfo.GetValue(o, BindingFlags.GetProperty, null, null, null)); 

       if (!isValid) 
       { 
        yield return validationAttribute.ErrorMessage; 
       } 
      } 
     } 
    } 
} 

public class Person 
{ 
    [Required(ErrorMessage = "Name is required!")] 
    public string Name { get; set; } 

    [Range(5, 20, ErrorMessage = "Must be between 5 and 20!")] 
    public int Age { get; set; } 
} 

Questo stampa il seguente alla console: è richiesto

Nome!
Deve essere compreso tra 5 e 20!

+0

Sì. Funziona perché gli attributi di annotazione dati implementano già un [metodo IsValid] (http://msdn.microsoft.com/en-us/library/cc679289 (v = vs.90) .aspx). Grazie! –

+2

Semplicemente fantastico! –

+0

Posso chiedere come convalidare gli attributi in caso di utilizzo di .Net 4.5? Sta usando 'TryToValidate'? –

0

Queste annotazioni di dati funzionano principalmente nel contesto di un altro framework, ad es. MVC w/Razor, Fluent ecc. Senza un altro framework le annotazioni sono solo questo, sono codice di identificazione e richiedono un framework/codice aggiuntivo per eseguire l'interpretazione.

L'annotazione di per sé non è vera AOP/Intercetta, e quindi le annotazioni non fanno nulla finché l'oggetto decorato con annotazione non viene inviato a un framework intermedio che sa interpretare/analizzare i codici dei marker (di solito tramite. Reflection).

Per un vero AoP che potrebbe far funzionare le annotazioni intrinsecamente, è necessario qualcosa come PostSharp/Unity, ecc. Queste strutture modificano l'IL in fase di esecuzione/compilazione e reindirizzano il codice originale.

+0

I dati non provengono da un'interfaccia utente; proviene da una fonte esterna che non controllo. In caso contrario, potrei semplicemente utilizzare la convalida fornita con Winforms o ASP.NET MVC. Non penso di aver bisogno di AOP in stile di iniezione del codice; vedi [Risposta di Patrick McGee] (http://stackoverflow.com/a/17286474/102937). –

+1

Hahah McGee; D Sono irlandese bene, ma non quello irlandese! –

6

Linq Versione

public static class Validator 
{ 
    public static IEnumerable<string> Validate(object o) 
     { 
      return TypeDescriptor 
       .GetProperties(o.GetType()) 
       .Cast<PropertyDescriptor>() 
       .SelectMany(pd => pd.Attributes.OfType<ValidationAttribute>() 
            .Where(va => !va.IsValid(pd.GetValue(o)))) 
            .Select(xx => xx.ErrorMessage); 
     } 
    } 
Problemi correlati