2010-04-17 2 views
12

Sto utilizzando VS 2010 RTM e sto tentando di eseguire alcune convalide di base su un tipo semplice utilizzando MetadataTypeAttribute. Quando inserisco l'attributo di validazione nella classe principale, tutto funziona. Tuttavia, quando lo metto nella classe dei metadati, sembra essere ignorato. Devo mancare qualcosa di banale, ma sono stato bloccato su questo per un po 'di tempo.Attributo .NET 4 RTM MetadataType ignorato quando si utilizza Validator

Ho esaminato il blocco di convalida di Enterprise Library come soluzione alternativa, ma non supporta la convalida di singole proprietà out of the box. Qualche idea?

class Program 
{ 
    static void Main(string[] args) 
    { 
     Stuff t = new Stuff(); 

     try 
     { 
      Validator.ValidateProperty(t.X, new ValidationContext(t, null, null) { MemberName = "X" }); 
      Console.WriteLine("Failed!"); 
     } 
     catch (ValidationException) 
     { 
      Console.WriteLine("Succeeded!"); 
     } 
    } 
} 

[MetadataType(typeof(StuffMetadata))] 
public class Stuff 
{ 
    //[Required] //works here 
    public string X { get; set; } 
} 

public class StuffMetadata 
{ 
    [Required] //no effect here 
    public string X { get; set; } 
} 

risposta

23

Sembra che il Validator non rispetta MetadataTypeAttribute:

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

Il rapporto deve essere esplicitamente iscritto:

TypeDescriptor.AddProviderTransparent(
     new AssociatedMetadataTypeTypeDescriptionProvider(
      typeof(Stuff), 
      typeof(StuffMetadata)), 
     typeof(Stuff)); 

Questa classe di supporto registrerà tutte le relazioni di metadati in un assembly:

public static class MetadataTypesRegister 
{ 
    static bool installed = false; 
    static object installedLock = new object(); 

    public static void InstallForThisAssembly() 
    { 
     if (installed) 
     { 
      return; 
     } 

     lock (installedLock) 
     { 
      if (installed) 
      { 
       return; 
      } 

      foreach (Type type in Assembly.GetExecutingAssembly().GetTypes()) 
      { 
       foreach (MetadataTypeAttribute attrib in type.GetCustomAttributes(typeof(MetadataTypeAttribute), true)) 
       { 
        TypeDescriptor.AddProviderTransparent(
         new AssociatedMetadataTypeTypeDescriptionProvider(type, attrib.MetadataClassType), type); 
       } 
      } 

      installed = true; 
     } 
    } 
} 
+1

Grazie per questo eccellente blurb di codice !! – aikeru

+0

Perché questo non è indicato nella lista MetadataTypeAttribute su MSDN? Sono stato appeso per un paio d'ore b/c nel mio progetto MVC tutto funziona bene, ma quando creo la mia app per Windows ho bisogno di spiegazioni –

2

Fornire un'istanza della classe metadata anziché della classe principale al costruttore ValidationContext sembra funzionare per me.

+0

Questo ha funzionato per me su "TryValidateProperty' ma non" TryValidateObject "purtroppo. –

+0

@Andy Avevo bisogno solo di ValidateProperty, quindi ho usato questo hack invece della soluzione completa dalla risposta accettata per motivi di codice più breve. – SlimShaggy

+0

Ottengo un 'ArgumentException' che 'l'istanza fornita funga corrisponde all'ObjectInstance sul validationcontext fornito'. –