2011-08-11 15 views
36

Estoy usando System.ComponentModel.DataAnnotations para proporcionar la validación de mi proyecto de Entity Framework 4.1.Cómo recuperar anotaciones de datos del código? (programáticamente)

Por ejemplo:

public class Player 
{ 
    [Required] 
    [MaxLength(30)] 
    [Display(Name = "Player Name")] 
    public string PlayerName { get; set; } 

    [MaxLength(100)] 
    [Display(Name = "Player Description")] 
    public string PlayerDescription{ get; set; } 
} 

necesito para recuperar el valor Display.Name anotación para mostrarlo en un mensaje como El elegido "Jugador Nombre" es Frank.

============================================= =================================

Otro ejemplo de por qué podría necesitar recuperar anotaciones :

var playerNameTextBox = new TextBox(); 
playerNameTextBox.MaxLength = GetAnnotation(myPlayer.PlayerName, MaxLength); 

¿Cómo puedo hacer eso?

+0

favor, eche un vistazo a este post http://stackoverflow.com/questions/803221/c-reflection-finding-attributes-on-a-member-field muestra cómo puedes hacerlo usando la reflexión. – Jethro

Respuesta

70

método de extensión:

public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute 
{ 
    var attrType = typeof(T); 
    var property = instance.GetType().GetProperty(propertyName); 
    return (T)property .GetCustomAttributes(attrType, false).First(); 
} 

Código:

var name = player.GetAttributeFrom<DisplayAttribute>("PlayerDescription").Name; 
var maxLength = player.GetAttributeFrom<MaxLengthAttribute>("PlayerName").Length; 
+2

Corrígeme si me equivoco, pero creo que no funcionaría si hubiera más de un DisplayAttribute presente en la clase Player (que casi siempre será el caso). Ver mi código actualizado en mi pregunta. – asmo

+0

código de muestra ha sido actualizado. – jgauffin

+0

Si la anotación no existe en el atributo, esto será explosivo.Si es posible que la anotación no exista, use 'FirstOrDefault()' en lugar de 'First()' –

0

Desea utilizar Reflection para lograr esto. Se puede encontrar una solución de trabajo here.

5

intente esto:

((DisplayAttribute) 
    (myPlayer 
    .GetType() 
    .GetProperty("PlayerName") 
    .GetCustomAttributes(typeof(DisplayAttribute),true)[0])).Name; 
0

una solución para el uso de la clase de metadatos con MetadataTypeAttribute de here

 public T GetAttributeFrom<T>(object instance, string propertyName) where T : Attribute 
    { 
     var attrType = typeof(T); 
     var property = instance.GetType().GetProperty(propertyName); 
     T t = (T)property.GetCustomAttributes(attrType, false).FirstOrDefault(); 
     if (t == null) 
     { 
      MetadataTypeAttribute[] metaAttr = (MetadataTypeAttribute[])instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true); 
      if (metaAttr.Length > 0) 
      { 
       foreach (MetadataTypeAttribute attr in metaAttr) 
       { 
        var subType = attr.MetadataClassType; 
        var pi = subType.GetField(propertyName); 
        if (pi != null) 
        { 
         t = (T)pi.GetCustomAttributes(attrType, false).FirstOrDefault(); 
         return t; 
        } 


       } 
      } 

     } 
     else 
     { 
      return t; 
     } 
     return null; 
    } 
0

Esta es la forma en que he hecho algo similar

/// <summary> 
/// Returns the DisplayAttribute of a PropertyInfo (field), if it fails returns null 
/// </summary> 
/// <param name="propertyInfo"></param> 
/// <returns></returns> 
private static string TryGetDisplayName(PropertyInfo propertyInfo) 
{ 
    string result = null; 
    try 
    { 
     var attrs = propertyInfo.GetCustomAttributes(typeof(DisplayAttribute), true); 
     if (attrs.Any()) 
      result = ((DisplayAttribute)attrs[0]).Name; 
    } 
    catch (Exception) 
    { 
     //eat the exception 
    } 
    return result; 
} 
1

Aquí están algunos métodos estáticos que puede utilizar para obtener el MaxLength, o cualquier otro atributo.

using System; 
using System.Linq; 
using System.Reflection; 
using System.ComponentModel.DataAnnotations; 
using System.Linq.Expressions; 

public static class AttributeHelpers { 

public static Int32 GetMaxLength<T>(Expression<Func<T,string>> propertyExpression) { 
    return GetPropertyAttributeValue<T,string,MaxLengthAttribute,Int32>(propertyExpression,attr => attr.Length); 
} 

//Optional Extension method 
public static Int32 GetMaxLength<T>(this T instance,Expression<Func<T,string>> propertyExpression) { 
    return GetMaxLength<T>(propertyExpression); 
} 


//Required generic method to get any property attribute from any class 
public static TValue GetPropertyAttributeValue<T, TOut, TAttribute, TValue>(Expression<Func<T,TOut>> propertyExpression,Func<TAttribute,TValue> valueSelector) where TAttribute : Attribute { 
    var expression = (MemberExpression)propertyExpression.Body; 
    var propertyInfo = (PropertyInfo)expression.Member; 
    var attr = propertyInfo.GetCustomAttributes(typeof(TAttribute),true).FirstOrDefault() as TAttribute; 

    if (attr==null) { 
     throw new MissingMemberException(typeof(T).Name+"."+propertyInfo.Name,typeof(TAttribute).Name); 
    } 

    return valueSelector(attr); 
} 

} 

Utilizando el método estático ...

var length = AttributeHelpers.GetMaxLength<Player>(x => x.PlayerName); 

o utilizando el método de extensión opcional en una instancia ...

var player = new Player(); 
var length = player.GetMaxLength(x => x.PlayerName); 

o utilizando el método estático completo para cualquier otro atributo (StringLength por ejemplo) ...

var length = AttributeHelpers.GetPropertyAttributeValue<Player,string,StringLengthAttribute,Int32>(prop => prop.PlayerName,attr => attr.MaximumLength); 

Inspirado por la respuesta aquí ... https://stackoverflow.com/a/32501356/324479

Cuestiones relacionadas