2013-01-17 5 views
8

I valori di enumerazione C# non sono limitati ai soli valori elencati nella sua definizione e possono memorizzare qualsiasi valore del suo tipo di base. Se il tipo di base non è definito rispetto a Int32 o semplicemente int viene utilizzato.Esiste validatore immediato per i valori Enum nello spazio dei nomi DataAnnotations?

Sto sviluppando un servizio WCF che deve essere sicuro che ad alcuni enum è assegnato un valore rispetto al valore predefinito per tutte le enumerazioni di 0. Comincio con un test unitario per scoprire se [Required] farebbe bene il lavoro qui .

using System.ComponentModel.DataAnnotations; 
using Xunit; 

public enum MyEnum 
{ 
    // I always start from 1 in order to distinct first value from the default value 
    First = 1, 
    Second, 
} 

public class Entity 
{ 
    [Required] 
    public MyEnum EnumValue { get; set; } 
} 

public class EntityValidationTests 
{ 
    [Fact] 
    public void TestValidEnumValue() 
    { 
     Entity entity = new Entity { EnumValue = MyEnum.First }; 

     Validator.ValidateObject(entity, new ValidationContext(entity, null, null)); 
    } 

    [Fact] 
    public void TestInvalidEnumValue() 
    { 
     Entity entity = new Entity { EnumValue = (MyEnum)(-126) }; 
     // -126 is stored in the entity.EnumValue property 

     Assert.Throws<ValidationException>(() => 
      Validator.ValidateObject(entity, new ValidationContext(entity, null, null))); 
    } 
} 

In caso contrario, il secondo test non genera eccezioni.

La mia domanda è: c'è un attributo validatore per verificare che il valore fornito sia Enum.GetValues?

Aggiornamento. Assicurarsi di utilizzare ValidateObject(Object, ValidationContext, Boolean) con l'ultimo parametro uguale a True anziché ValidateObject(Object, ValidationContext) come eseguito nel test dell'unità.

+0

ho mai usato, quindi non so se controlla i valori, ma potresti provare EnumDataTypeAttribute: http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.enumdatatypeattribute%28v=vs.95%29 .aspx –

risposta

14

C'è EnumDataType in .NET4 + ...

Assicurarsi di impostare il terzo parametro, validateAllProperties=true nella chiamata a ValidateObject

così dal vostro esempio:

public class Entity 
{ 
    [EnumDataType(typeof(MyEnum))] 
    public MyEnum EnumValue { get; set; } 
} 

[Fact] 
public void TestInvalidEnumValue() 
{ 
    Entity entity = new Entity { EnumValue = (MyEnum)(-126) }; 
    // -126 is stored in the entity.EnumValue property 

    Assert.Throws<ValidationException>(() => 
     Validator.ValidateObject(entity, new ValidationContext(entity, null, null), true)); 
} 
+0

Appena passato da' [Required] 'a' [EnumDataType (typeof (MyEnum))] 'e testato, ancora no' ValidationException' – Mike

+0

hai provato entrambi gli attributi? – qujck

+0

sicuro di aver provato entrambi anche – Mike

10

Quello che stai cercando è:

Enum.IsDefined(typeof(MyEnum), entity.EnumValue) 

[Update + 1]

Il fuori del validatore scatola che fa un sacco di convalide compreso questo è chiamato EnumDataType. Assicurati di impostare validateAllProperties = true come ValidateObject, altrimenti il ​​test fallirà.

Se si desidera solo per controllare se l'enumerazione è definito, è possibile utilizzare un validatore personalizzato con la linea precedente:

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method, AllowMultiple = false)] 
    public sealed class EnumValidateExistsAttribute : DataTypeAttribute 
    { 
     public EnumValidateExistsAttribute(Type enumType) 
      : base("Enumeration") 
     { 
      this.EnumType = enumType; 
     } 

     public override bool IsValid(object value) 
     { 
      if (this.EnumType == null) 
      { 
       throw new InvalidOperationException("Type cannot be null"); 
      } 
      if (!this.EnumType.IsEnum) 
      { 
       throw new InvalidOperationException("Type must be an enum"); 
      } 
      if (!Enum.IsDefined(EnumType, value)) 
      { 
       return false; 
      } 
      return true; 
     } 

     public Type EnumType 
     { 
      get; 
      set; 
     } 
    } 

... ma suppongo che non è fuori dalla scatola, allora è vero?

+0

+1 per questo lui metodo lpful. È stato lì per anni, ma non l'ho mai notato – Mike

+0

@ RaphaëlAlthaus hai assolutamente ragione. Ci scusiamo per questo, ho cambiato la mia risposta e l'ho testata, questo funziona. – atlaste

+0

@StefandeBruijn fine e +1 –

Problemi correlati