Member 13081540 Ответов: 2

Получить пользовательское значение атрибута с помощью метода расширения


Привет,

Я пытаюсь получить пользовательский атрибут для значения перечисления, используя метод расширения, который может использовать каждое значение перечисления. Когда я пытаюсь вызвать GetCustomAttributes, он всегда ничего не возвращает.

Что я уже пробовал:

В основном у меня есть тестовое перечисление, которое имеет пользовательский атрибут с параметром 'name'

private enum TestEnum
{
    [Enum("Whatever")]
    Unknown = 0
}


Это метод расширения, который используется для извлечения "чего угодно"
public static string ToDisplayName(this Enum value)
{
    var type = value.GetType();
    var attributes = type.GetTypeInfo().GetCustomAttributes(typeof(Enum),true);

    return ((EnumAttribute)attributes[0]).Name;
}


переменная атрибутов всегда пуста.

И это обычай:
var testEnum = TestEnum.Unknown;
var result = testEnum.ToDisplayName();


Заранее спасибо

2 Ответов

Рейтинг:
2

Richard Deeming

Чтобы добавить к ответу Билла, есть несколько проблем с вашим исходным кодом.

var type = value.GetType();
var attributes = type.GetTypeInfo().GetCustomAttributes(...);
Вы ищете атрибуты для самого типа перечисления, а не атрибуты для члена перечисления. Так:
[Enum("...")] private enum TestEnum { ... }
совпадало бы, но:
private enum TestEnum { [Enum("...")] Unknown }
не будет.

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

.GetCustomAttributes(typeof(Enum), true);
Тип, который вы передаете в качестве первого параметра здесь, должен быть типом атрибута, который вы ищете. Но вместо того чтобы пройти мимо typeof(EnumAttribute)- ты проходишь мимо typeof(Enum) Это и есть то самое System.Enum класс, который не является атрибутом и не будет соответствовать вашему пользовательскому атрибуту.

return ((EnumAttribute)attributes[0]).Name;
GetCustomAttributes возвращает пустой массив, если нет соответствующих атрибутов. Если это произойдет, ваш код выдаст IndexOutOfRangeException Вы должны проверить, был ли атрибут найден, и вернуть подходящую альтернативу, если она не была найдена.

Вы можете исправить свой код довольно легко:
public static string ToDisplayName(this Enum value)
{
    var enumType = value.GetType().GetTypeInfo();
    var valueField = enumType.GetDeclaredField(value.ToString());
    var attributes = valueField.GetCustomAttributes<EnumAttribute>(false);
    if (attributes.Length == 0) return value.ToString();
    return attributes[0].Name;
}


Рейтинг:
19

BillWoodruff

Я думаю, что вы хотите использовать встроенный атрибут DescriptionAttribute, который упростит код:

public static class EnumExtensions
{
    public static string ToDisplayName(this Enum value)
    {
        Type type = value.GetType();
        
        MemberInfo[] memInfo = type.GetMember(value.ToString());

        // no attributes found ?
        if (memInfo.Length == 0) return string.Empty;
       
        // cast to Array or List required 
        // an IEnumerable of DescriptionAttribute cannot be indexed !
        DescriptionAttribute[] attributes = memInfo[0].GetCustomAttributes<DescriptionAttribute>(false).ToArray();

        // handle value without description
        return (attributes.Length == 0) ? string.Empty : attributes[0].Description;
    }
}
Использование:
public enum TestEnum
{
    [Description("Whatever")]
    Unknown = 0,
    NoDescription
}

// sample calls
string des0 = TestEnum.Unknown.ToDisplayName();
string des1 = TestEnum.NoDescription.ToDisplayName();