Добавление информации заголовка в перечисление с использованием пользовательского атрибута в C# - PullRequest
0 голосов
/ 10 января 2020

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

Например, рассмотрим следующее перечисление:

    [EnumSize(0x30000)]
    public enum Memories
    { 
        [MemSize(0x10000)]
        [Description("Memory0")]
        Memory0Base = 0x00000,

        [MemSize(0x10000)]
        [Description("Memory1")]
        Memory1Base= 0x10000,

        [MemSize(0x10000)]
        [Description("Memory2")]
        Memory2Base= 0x20000
    }

Теперь я создал атрибуты EnumSize и MemSize следующим образом:

public class EnumSizeAttribute : System.Attribute
{
    private int _value;
    public EnumSizeAttribute(int value)
    {
        _value = value;
    }
    public int Value
    {
        get { return _value; }
    }
}

И сделал это более «дружественный доступ» (то есть я могу сделать что-то вроде этого: Memories.Memory2Base.MemSize () или Memories.EnumSize ()):

public static string EnumSize<T>(this T value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    EnumSizeAttribute[] attributes = (EnumSizeAttribute[])fi.GetCustomAttributes(typeof(EnumSizeAttribute), false);

    if (attributes.Length > 0)
        return attributes[0].EnumSize();
    else
        return value.ToString();
}

Теперь, хотя он не генерирует ошибку компиляции при использовании его как заголовок моего перечисления, как здесь ниже, я не могу получить EnumSize, выполнив "Memories.EnumSize ()".

[EnumSize(0x30000)]
public enum Memories
{ 
 ...
}

Любой совет, как заставить его работать, был бы очень признателен.

1 Ответ

2 голосов
/ 10 января 2020

Memories - это тип, а не поле, поэтому вам нужно сделать что-то вроде этого:

public static string EnumSize<T>() where T : struct, Enum
{
    EnumSizeAttribute attribute = typeof(T).GetCustomAttribute<EnumSizeAttribute>();

    return attribute?.Value.ToString();
}

И использовать следующим образом:

string size = EnumSize<Memories>();

Вы не будете быть в состоянии вызвать это как метод расширения, как у вас с MemSize.

Единственный способ сделать это - расширить Type, например:

public static string EnumSize(this Type type)
{
    EnumSizeAttribute attribute = type.GetCustomAttribute<EnumSizeAttribute>();

    return attribute?.Value.ToString();
}

string size = Memories.EnumSize();

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

Конечно, вы можете вызвать исключение, если оно используется неправильно:

public static string EnumSize(this Type type)
{
    if (!type.IsEnum)
    {
        throw new InvalidOperationException("EnumSize only applies to enums");
    }

    EnumSizeAttribute attribute = type.GetCustomAttribute<EnumSizeAttribute>();

    return attribute?.Value.ToString();
}

Но я бы, наверное, остановился на первом примере.

...