Cómo recuperar Anotaciones de datos de código? (programáticamente)
Estoy usando System.ComponentModel.DataAnnotations
para proporcionar validación para mi proyecto Entity Framework 4.1.
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 recuperar el valor de anotación Display.Name
para mostrarlo en un mensaje como El "Nombre del jugador" elegido 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?
6 answers
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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-11 18:42:45
Prueba esto:
((DisplayAttribute)
(myPlayer
.GetType()
.GetProperty("PlayerName")
.GetCustomAttributes(typeof(DisplayAttribute),true)[0])).Name;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-18 14:50:03
Aquí hay algunos métodos estáticos que puede usar 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);
}
}
Usando el método estático...
var length = AttributeHelpers.GetMaxLength<Player>(x => x.PlayerName);
O usando el método de extensión opcional en una instancia...
var player = new Player();
var length = player.GetMaxLength(x => x.PlayerName);
O usando 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:32:20
Desea utilizar la Reflexión para lograr esto. Una solución de trabajo se puede encontrar aquí.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:17:38
Una solución para usar la clase de metadatos con MetadataTypeAttribute de aquí
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:06
Así es como 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-18 14:13:35