получить значение атрибута DisplayName - PullRequest
60 голосов
/ 16 февраля 2011
public class Class1
{
    [DisplayName("Something To Name")]
    public virtual string Name { get; set; }
}

Как получить значение атрибута DisplayName в C #?

Ответы [ 13 ]

74 голосов
/ 16 февраля 2011

Попробуйте эти мои полезные методы:

using System.ComponentModel;
using System.Globalization;
using System.Linq;


public static T GetAttribute<T>(this MemberInfo member, bool isRequired)
    where T : Attribute
{
    var attribute = member.GetCustomAttributes(typeof(T), false).SingleOrDefault();

    if (attribute == null && isRequired)
    {
        throw new ArgumentException(
            string.Format(
                CultureInfo.InvariantCulture, 
                "The {0} attribute must be defined on member {1}", 
                typeof(T).Name, 
                member.Name));
    }

    return (T)attribute;
}

public static string GetPropertyDisplayName<T>(Expression<Func<T, object>> propertyExpression)
{
    var memberInfo = GetPropertyInformation(propertyExpression.Body);
    if (memberInfo == null)
    {
        throw new ArgumentException(
            "No property reference expression was found.",
            "propertyExpression");
    }

    var attr = memberInfo.GetAttribute<DisplayNameAttribute>(false);
    if (attr == null)
    {
        return memberInfo.Name;
    }

    return attr.DisplayName;
}

public static MemberInfo GetPropertyInformation(Expression propertyExpression)
{
    Debug.Assert(propertyExpression != null, "propertyExpression != null");
    MemberExpression memberExpr = propertyExpression as MemberExpression;
    if (memberExpr == null)
    {
        UnaryExpression unaryExpr = propertyExpression as UnaryExpression;
        if (unaryExpr != null && unaryExpr.NodeType == ExpressionType.Convert)
        {
            memberExpr = unaryExpr.Operand as MemberExpression;
        }
    }

    if (memberExpr != null && memberExpr.Member.MemberType == MemberTypes.Property)
    {
        return memberExpr.Member;
    }

    return null;
}

Использование будет:

string displayName = ReflectionExtensions.GetPropertyDisplayName<SomeClass>(i => i.SomeProperty);
29 голосов
/ 16 февраля 2011

Вам необходимо получить PropertyInfo, связанное со свойством (например, через typeof(Class1).GetProperty("Name")), а затем вызвать GetCustomAttributes.

Это немного грязно из-за возврата нескольких значений- вы можете захотеть написать вспомогательный метод, чтобы сделать это, если вам это нужно из нескольких мест.(Возможно, где-то уже есть вспомогательный метод в фреймворке, но если он есть, я об этом не знаю.)

РЕДАКТИРОВАТЬ: Как отметил Леппи, есть такой метод:Attribute.GetCustomAttribute(MemberInfo, Type)

26 голосов
/ 16 февраля 2011

Прежде всего, вам нужно получить объект MemberInfo, который представляет это свойство.Вам нужно будет сделать некоторую форму отражения:

MemberInfo property = typeof(Class1).GetProperty("Name");

(я использую отражение в старом стиле, но вы также можете использовать дерево выражений, если у вас есть доступ к типу во время компиляции)

Затем вы можете получить атрибут и получить значение свойства DisplayName:

var attribute = property.GetCustomAttributes(typeof(DisplayNameAttribute), true)
      .Cast<DisplayNameAttribute>().Single();
string displayName = attribute.DisplayName;

() в скобках требуется опечатка

12 голосов
/ 04 декабря 2013

Если кому-то интересно получить локализованную строку из свойства с DisplayAttribute и ResourceType , например:

[Display(Name = "Year", ResourceType = typeof(ArrivalsResource))]
public int Year { get; set; }

Используйте следующее после displayAttribute != null(как показано выше @ alex 'answer ):

ResourceManager resourceManager = new ResourceManager(displayAttribute.ResourceType);
var entry = resourceManager.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true)
                           .OfType<DictionaryEntry>()
                           .FirstOrDefault(p => p.Key.ToString() == displayAttribute.Name);

return entry.Value.ToString();
12 голосов
/ 16 февраля 2011

Изнутри представления, имеющего Class1 в качестве модели представления со строгим типом:

ModelMetadata.FromLambdaExpression<Class1, string>(x => x.Name, ViewData).DisplayName;
6 голосов
/ 07 апреля 2012

Хорошие занятия от Rich Tebb! Я использую DisplayAttribute, и код не работает для меня. Единственное, что я добавил, это обработка DisplayAttribute. Краткий поиск показал, что этот атрибут является новым для MVC3 и .Net 4 и делает почти то же самое, а также многое другое. Вот модифицированная версия метода:

 public static string GetPropertyDisplayString<T>(Expression<Func<T, object>> propertyExpression)
    {
        var memberInfo = GetPropertyInformation(propertyExpression.Body);
        if (memberInfo == null)
        {
            throw new ArgumentException(
                "No property reference expression was found.",
                "propertyExpression");
        }

        var displayAttribute = memberInfo.GetAttribute<DisplayAttribute>(false);

        if (displayAttribute != null)
        {
            return displayAttribute.Name;
        }
        else
        {
            var displayNameAttribute = memberInfo.GetAttribute<DisplayNameAttribute>(false);
            if (displayNameAttribute != null)
            {
                return displayNameAttribute.DisplayName;
            }
            else
            {
                return memberInfo.Name;
            }
        }
    }
4 голосов
/ 02 января 2018
var propInfo = new Class1().GetType().GetProperty("Name");
var displayNameAttribute = propInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
var displayName = displayNameAttribute[0] as DisplayNameAttribute).DisplayName;

displayName переменная теперь содержит значение свойства.

4 голосов
/ 03 декабря 2014

У меня есть этот универсальный вспомогательный метод.Я передаю список заданного типа (при условии, что у вас есть вспомогательный класс), и он генерирует таблицу данных со свойствами в качестве заголовков столбцов и элементов списка в качестве данных.

Так же, как в стандартном MVC, если вы неопределив атрибут DisplayName, он будет возвращаться к имени свойства, поэтому вы должны включать DisplayName только в том случае, если оно отличается от имени свойства.

    public DataTable BuildDataTable<T>(IList<T> data)
    {
        //Get properties
        PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
        //.Where(p => !p.GetGetMethod().IsVirtual && !p.GetGetMethod().IsFinal).ToArray(); //Hides virtual properties

        //Get column headers
        bool isDisplayNameAttributeDefined = false;
        string[] headers = new string[Props.Length];
        int colCount = 0;
        foreach (PropertyInfo prop in Props)
        {
            isDisplayNameAttributeDefined = Attribute.IsDefined(prop, typeof(DisplayNameAttribute));

            if (isDisplayNameAttributeDefined)
            {
                DisplayNameAttribute dna = (DisplayNameAttribute)Attribute.GetCustomAttribute(prop, typeof(DisplayNameAttribute));
                if (dna != null)
                    headers[colCount] = dna.DisplayName;
            }
            else
                headers[colCount] = prop.Name;

            colCount++;
            isDisplayNameAttributeDefined = false;
        }

        DataTable dataTable = new DataTable(typeof(T).Name);

        //Add column headers to datatable
        foreach (var header in headers)
            dataTable.Columns.Add(header);

        dataTable.Rows.Add(headers);

        //Add datalist to datatable
        foreach (T item in data)
        {
            object[] values = new object[Props.Length];
            for (int col = 0; col < Props.Length; col++)
                values[col] = Props[col].GetValue(item, null);

            dataTable.Rows.Add(values);
        }

        return dataTable;
    }

Если есть более эффективный / безопасный способ сделать это,Я бы оценил любой отзыв.Закомментированное предложение // Where будет отфильтровывать виртуальные свойства.Полезно, если вы используете классы моделей напрямую, так как EF вводит свойства «Навигация» как виртуальные.Однако он также отфильтрует любые ваши собственные виртуальные свойства, если вы решите расширить такие классы.По этой причине я предпочитаю создать ViewModel и украсить его только необходимыми свойствами и отображаемыми атрибутами по мере необходимости, а затем составить их список.

Надеюсь, это поможет.

3 голосов
/ 02 июня 2014
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(foo);

foreach (PropertyDescriptor property in properties)
{
    if (property.Name == "Name")
    {
        Console.WriteLine(property.DisplayName); // Something To Name
    }
}

, где foo - это экземпляр Class1

1 голос
/ 08 марта 2017

Попробуйте этот код:

EnumEntity.item.GetType().GetFields()[(int)EnumEntity.item].CustomAttributes.ToArray()[0].NamedArguments[0].TypedValue.ToString()

Это даст вам значение атрибута данных Name.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...