Reflection – получить имя атрибута и значение свойства

У меня есть class, давайте назовем его Book с именем Name. С этим свойством у меня есть атрибут, связанный с ним.

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

В моем основном методе я использую reflection и хочу получить пару ключевых значений каждого атрибута для каждого свойства. Поэтому в этом примере я ожидаю увидеть «Author» для имени атрибута и «AuthorName» для значения атрибута.

Вопрос: Как получить имя и значение атрибута в моих свойствах с помощью Reflection?

13 Solutions collect form web for “Reflection – получить имя атрибута и значение свойства”

Используйте typeof(Book).GetProperties() чтобы получить массив экземпляров PropertyInfo . Затем используйте GetCustomAttribute() для каждого PropertyInfo чтобы узнать, есть ли у каждого из них тип атрибута Author . Если это так, вы можете получить имя свойства из информации свойства и значений атрибута из атрибута.

Что-то в этом направлении сканирует тип свойств, которые имеют определенный тип атрибута и возвращают данные в словаре (обратите внимание, что это можно сделать более динамичным, передав типы в подпрограмму):

 public static Dictionary GetAuthors() { Dictionary _dict = new Dictionary(); 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; } 

Чтобы получить все атрибуты свойства в словаре, используйте это:

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

не забудьте изменить значение false на true, если вы хотите также включить наследуемые атрибуты.

ЕСЛИ вы просто хотите одно конкретное значение атрибута. Например, Display Attribute вы можете использовать следующий код.

 var pInfo = typeof(Book).GetProperty("Name") .GetCustomAttribute(); var name = pInfo.Name; 

Я решил аналогичные проблемы, написав Generic Extension Property Attribute Helper:

 using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; public static class AttributeHelper { public static TValue GetPropertyAttributeValue( Expression> propertyExpression, Func 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); } } 

Применение:

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

Вы можете использовать GetCustomAttributesData() и GetCustomAttributes() :

 var attributeData = typeof(Book).GetProperty("Name").GetCustomAttributesData(); var attributes = typeof(Book).GetProperty("Name").GetCustomAttributes(false); 

Если вы имеете в виду «для атрибутов, которые принимают один параметр, CustomAttributeData имена атрибутов и значение параметра», то это проще в .NET 4.5 с помощью 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 GetPropertyAttributes(PropertyInfo property) { Dictionary attribs = new Dictionary(); // 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; } } 
 private static Dictionary GetAuthors() { return typeof(Book).GetProperties() .SelectMany(prop => prop.GetCustomAttributes()) .OfType() .ToDictionary(attribute => attribute.Name, attribute => attribute.Name); } 
 public static class PropertyInfoExtensions { public static TValue GetAttributValue(this PropertyInfo prop, Func value) where TAttribute : Attribute { var att = prop.GetCustomAttributes( typeof(TAttribute), true ).FirstOrDefault() as TAttribute; if (att != null) { return value(att); } return default(TValue); } } 

Применение:

  //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); } 

или:

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

Necromancing.
Для тех, кому еще нужно поддерживать .NET 2.0 или тех, кто хочет это сделать без 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(System.Reflection.MemberInfo mi) { return (T)GetAttribute(mi, typeof(T)); } public delegate TResult GetValue_t(T arg1); public static TValue GetAttributValue(System.Reflection.MemberInfo mi, GetValue_t 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); } 

Пример использования:

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

или просто

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

В этом примере я использовал DisplayName вместо Author, потому что у него есть поле с именем DisplayName, которое будет отображаться со значением.

Вот несколько статических методов, которые вы можете использовать для получения MaxLength или любого другого атрибута.

 using System; using System.Linq; using System.Reflection; using System.ComponentModel.DataAnnotations; using System.Linq.Expressions; public static class AttributeHelpers { public static Int32 GetMaxLength(Expression> propertyExpression) { return GetPropertyAttributeValue(propertyExpression,attr => attr.Length); } //Optional Extension method public static Int32 GetMaxLength(this T instance,Expression> propertyExpression) { return GetMaxLength(propertyExpression); } //Required generic method to get any property attribute from any class public static TValue GetPropertyAttributeValue(Expression> propertyExpression,Func 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); } } 

Использование статического метода …

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

Или используя дополнительный метод расширения на экземпляре …

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

Или используя полный статический метод для любого другого атрибута (например, StringLength) …

 var length = AttributeHelpers.GetPropertyAttributeValue(prop => prop.PlayerName,attr => attr.MaximumLength); 

Вдохновленный ответом Микаэля Энгвера.

для получения атрибута из enums, я использую:

  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(); } 

// С помощью

  var _message = Translate(code); 

Просто ищите подходящее место для размещения этого fragmentа кода.

скажем, у вас есть следующее свойство:

 [Display(Name = "Solar Radiation (Average)", ShortName = "SolarRadiationAvg")] public int SolarRadiationAvgSensorId { get; set; } 

И вы хотите получить значение ShortName. Ты можешь сделать:

 ((DisplayAttribute)(typeof(SensorsModel).GetProperty(SolarRadiationAvgSensorId).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName; 

Или сделать его общим:

 internal static string GetPropertyAttributeShortName(string propertyName) { return ((DisplayAttribute)(typeof(SensorsModel).GetProperty(propertyName).GetCustomAttribute(typeof(DisplayAttribute)))).ShortName; } 
  • Можно ли установить частную собственность через reflection?
  • Поиск значения enums по его описанию Атрибут
  • В чем разница между a.getClass () и A.class в Java?
  • Как получить значение свойства с помощью отражения
  • Разрешить тип от имени classа в другой сборке
  • Отражение. Получение общих параметров из экземпляра System.Type.
  • В чем разница между динамическим прокси JDK и CGLib?
  • Создание classа из строки и создание экземпляра в Scala 2.10
  • Вызов статического метода с reflectionм
  • Как проверить, является ли тип примитивным
  • Как вы можете получить имена параметров метода?
  • Давайте будем гением компьютера.