property enum c# reflection propertyinfo

c# - enum - Reflexión: obtenga el nombre y el valor del atributo en la propiedad



getproperty c# reflection (12)

Aquí hay algunos métodos estáticos que puede usar para obtener 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 de Mikael Engver.

Tengo una clase, vamos a llamarlo Libro con una propiedad llamada Nombre. Con esa propiedad, tengo un atributo asociado a ella.

public class Book { [Author("AuthorName")] public string Name { get; private set; } }

En mi método principal, estoy usando el reflejo y deseo obtener un par de valores clave de cada atributo para cada propiedad. Por lo tanto, en este ejemplo, esperaría ver "Autor" para el nombre del atributo y "Nombre del autor" para el valor del atributo.

Pregunta: ¿Cómo obtengo el nombre y el valor del atributo en mis propiedades usando Reflection?


He resuelto problemas similares escribiendo un Ayudante de atributo de propiedad de extensión genérica:

using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; public static class AttributeHelper { 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; return attr != null ? valueSelector(attr) : default(TValue); } }

Uso:

var author = AttributeHelper.GetPropertyAttributeValue<Book, string, AuthorAttribute, string>(prop => prop.Name, attr => attr.Author); // author = "AuthorName"


Nigromancia
Para aquellos que todavía tienen que mantener .NET 2.0, o aquellos que quieren hacerlo sin LINQ:

public static object GetAttribute(System.Reflection.MemberInfo mi, System.Type t) { object[] objs = mi.GetCustomAttributes(t, true); if (objs == null || objs.Length < 1) return null; return objs[0]; } public static T GetAttribute<T>(System.Reflection.MemberInfo mi) { return (T)GetAttribute(mi, typeof(T)); } public delegate TResult GetValue_t<in T, out TResult>(T arg1); public static TValue GetAttributValue<TAttribute, TValue>(System.Reflection.MemberInfo mi, GetValue_t<TAttribute, TValue> value) where TAttribute : System.Attribute { TAttribute[] objAtts = (TAttribute[])mi.GetCustomAttributes(typeof(TAttribute), true); TAttribute att = (objAtts == null || objAtts.Length < 1) ? default(TAttribute) : objAtts[0]; // TAttribute att = (TAttribute)GetAttribute(mi, typeof(TAttribute)); if (att != null) { return value(att); } return default(TValue); }

Ejemplo de uso:

System.Reflection.FieldInfo fi = t.GetField("PrintBackground"); wkHtmlOptionNameAttribute att = GetAttribute<wkHtmlOptionNameAttribute>(fi); string name = GetAttributValue<wkHtmlOptionNameAttribute, string>(fi, delegate(wkHtmlOptionNameAttribute a){ return a.Name;});

o simplemente

string aname = GetAttributValue<wkHtmlOptionNameAttribute, string>(fi, a => a.Name );


Para obtener todos los atributos de una propiedad en un diccionario, usa esto:

typeof(Book) .GetProperty("Name") .GetCustomAttributes(false) .ToDictionary(a => a.GetType().Name, a => a);

recuerde cambiar a falso en verdadero si también desea incluir atributos heredados.



SI solo quiere un valor de atributo específico Por ejemplo, atributo de visualización, puede usar el siguiente código.

var pInfo = typeof(Book).GetProperty("Name") .GetCustomAttributes(typeof(DisplayAttribute),false) .Cast<DisplayAttribute>().FirstOrDefault(); var name = pInfo.Name;


Si quiere decir "para los atributos que toman un parámetro, enumere los nombres de los atributos y el valor del parámetro", entonces esto es más fácil en .NET 4.5 a través de la API CustomAttributeData :

using System.Collections.Generic; using System.ComponentModel; using System.Reflection; public static class Program { static void Main() { PropertyInfo prop = typeof(Foo).GetProperty("Bar"); var vals = GetPropertyAttributes(prop); // has: DisplayName = "abc", Browsable = false } public static Dictionary<string, object> GetPropertyAttributes(PropertyInfo property) { Dictionary<string, object> attribs = new Dictionary<string, object>(); // look for attributes that takes one constructor argument foreach (CustomAttributeData attribData in property.GetCustomAttributesData()) { if(attribData.ConstructorArguments.Count == 1) { string typeName = attribData.Constructor.DeclaringType.Name; if (typeName.EndsWith("Attribute")) typeName = typeName.Substring(0, typeName.Length - 9); attribs[typeName] = attribData.ConstructorArguments[0].Value; } } return attribs; } } class Foo { [DisplayName("abc")] [Browsable(false)] public string Bar { get; set; } }


Utilice typeof(Book).GetProperties() para obtener una matriz de instancias de PropertyInfo . Luego use GetCustomAttribute() en cada PropertyInfo para ver si alguno de ellos tiene el tipo de atributo de Author . Si lo hacen, puede obtener el nombre de la propiedad de la información de la propiedad y los valores de atributo del atributo.

Algo similar a esto para escanear un tipo de propiedades que tienen un tipo de atributo específico y para devolver datos en un diccionario (tenga en cuenta que esto se puede hacer más dinámico pasando tipos a la rutina):

public static Dictionary<string, string> GetAuthors() { Dictionary<string, string> _dict = new Dictionary<string, string>(); PropertyInfo[] props = typeof(Book).GetProperties(); foreach (PropertyInfo prop in props) { object[] attrs = prop.GetCustomAttributes(true); foreach (object attr in attrs) { AuthorAttribute authAttr = attr as AuthorAttribute; if (authAttr != null) { string propName = prop.Name; string auth = authAttr.Name; _dict.Add(propName, auth); } } } return _dict; }


para obtener el atributo de enum, estoy usando:

public enum ExceptionCodes { [ExceptionCode(1000)] InternalError, } public static (int code, string message) Translate(ExceptionCodes code) { return code.GetType() .GetField(Enum.GetName(typeof(ExceptionCodes), code)) .GetCustomAttributes(false).Where((attr) => { return (attr is ExceptionCodeAttribute); }).Select(customAttr => { var attr = (customAttr as ExceptionCodeAttribute); return (attr.Code, attr.FriendlyMessage); }).FirstOrDefault(); }

// Utilizando

var _message = Translate(code);


foreach (var p in model.GetType().GetProperties()) { var valueOfDisplay = p.GetCustomAttributesData() .Any(a => a.AttributeType.Name == "DisplayNameAttribute") ? p.GetCustomAttribute<DisplayNameAttribute>().DisplayName : p.Name; }

En este ejemplo, utilicé DisplayName en lugar de Author porque tiene un campo llamado ''DisplayName'' para mostrar con un valor.


private static Dictionary<string, string> GetAuthors() { return typeof(Book).GetProperties() .SelectMany(prop => prop.GetCustomAttributes()) .OfType<AuthorAttribute>() .ToDictionary(attribute => attribute.Name, attribute => attribute.Name); }


public static class PropertyInfoExtensions { public static TValue GetAttributValue<TAttribute, TValue>(this PropertyInfo prop, Func<TAttribute, TValue> value) where TAttribute : Attribute { var att = prop.GetCustomAttributes( typeof(TAttribute), true ).FirstOrDefault() as TAttribute; if (att != null) { return value(att); } return default(TValue); } }

Uso:

//get class properties with attribute [AuthorAttribute] var props = typeof(Book).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(AuthorAttribute))); foreach (var prop in props) { string value = prop.GetAttributValue((AuthorAttribute a) => a.Name); }

o:

//get class properties with attribute [AuthorAttribute] var props = typeof(Book).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(AuthorAttribute))); IList<string> values = props.Select(prop => prop.GetAttributValue((AuthorAttribute a) => a.Name)).Where(attr => attr != null).ToList();