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

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

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

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

Вопрос: Как получить имя и значение атрибута в моих свойствах с помощью 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
  • Java - получить список всех classов, загруженных в JVM
  • Использование IsAssignableFrom и ключевое слово «is» в C #
  • Convert.ChangeType () не работает в Nullable Types
  • Как я могу получить все classы в пространстве имен?
  • Получить имя и тип свойства, используя выражение lambda
  • Когда вы используете reflection? Модели / анти-паттерны
  • Почему в C # нет оператора `fieldof` или` methodof`?
  • Разница между загрузкой classа с использованием ClassLoader и Class.forName
  • Почему GetType возвращает System.Int32 вместо Nullable ?
  • Как вызвать метод расширения с помощью отражения?
  • Interesting Posts

    Каков наилучший тип данных для использования в c #?

    Разделы для двойной загрузки установите Ubuntu с Windows

    .NET. Каков наилучший способ реализации «catch all exceptions handler»

    Пароль сброса идентификатора ASP.NET

    Возврат значения из streamа?

    Сравнить контрольную сумму с Fdupes только для папок с определенным именем?

    загрузка файла PDF

    Photoshop CS4, мой инструмент линии теперь рисует стрелки, как мне вернуть значение по умолчанию и что это такое?

    Как сортировать быстрый массив, содержащий экземпляры подclassа NSManagedObject, по значению атрибута (date)

    Создание входного streamа из постоянной памяти

    Как я могу удалить кнопку или сделать ее невидимой в Android?

    Как сохранить список объектов в настройках приложения

    Являются ли SSD полезными для разработки программного обеспечения?

    Почему мой оператор мощности (^) не работает?

    Создание отдельного списка настраиваемого типа в C #

    Давайте будем гением компьютера.