Создать собственный атрибут DisplayAttribute для перечислений?

У меня есть класс enum...

public enum LeadStatus : byte
{
    [Display(Name = "Created")] Created = 1,
    [Display(Name = "Assigned")] Assigned = 2,
    ....
}

Name конечно из коробки. Из метаданных...

namespace System.ComponentModel.DataAnnotations
{
    public sealed class DisplayAttribute : Attribute
    {
        ...
        public string Name { get; set; }
        ...
    }
}

Предположим, что мне нужен мой собственный атрибут отображения, такой как "BackgroundColor"...

[Display(Name = "Created", BackgroundColor="green")] Created = 1

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

Спасибо!

3 ответа

Имея свой собственный атрибут.

public sealed class ExtrasDisplayAttribute : Attribute
{
    public string Name { get; set; }
    public string BackgroundColor { get; set; }
}

И это метод расширения.

namespace ExtensionsNamespace
{
    public static class Extensions
    {
        public static TAttribute GetAttribute<TAttribute>(Enum value) where TAttribute : Attribute
        {
            return value.GetType()
                .GetMember(value.ToString())[0]
                .GetCustomAttribute<TAttribute>();
        }
    }
}

Теперь вы можете извлечь атрибут из enum следующим образом.

using static ExtensionsNamespace.Extensions;

//...

var info = GetAttribute<ExtrasDisplayAttribute>(LeadStatus.Created);
var name = info.Name;
var bg = info.BackgroundColor;

//...

public enum LeadStatus : byte
{
    [ExtrasDisplay(Name = "Created", BackgroundColor = "Red")] Created = 1,
    [ExtrasDisplay(Name = "Assigned")] Assigned = 2,
}

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

public enum LeadStatus : byte
{
    [Display(Name = "Created"), ExtrasDisplay(BackgroundColor = "Red")]Created = 1,
    [Display(Name = "Assigned")] Assigned = 2,
}

И извлеките каждый, который вы хотите.

var name = GetAttribute<DisplayAttribute>(LeadStatus.Created).Name;
var bg = GetAttribute<ExtrasDisplayAttribute>(LeadStatus.Created).BackgroundColor;

public sealed class DisplayAttribute : Attribute это закрытый класс, и поэтому вы не можете наследовать его и добавлять к нему другое поведение или свойства.

Ниже мое предположение, но кто-то может вмешаться, если они знают, почему

И вы можете задаться вопросом, почему разработчики.NET сделали это закрытым? Мне интересно то же самое, и я предполагаю, что каждый из свойств в DisplayAttribute используются для внедрения JavaScript, HTML и т. д. Если они оставили его открытым, и вы добавили BackgroundColor собственность на это, что это значит? Что это будет делать в пользовательском интерфейсе?

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

Методы внутри перечисления в C#

Другие вопросы по тегам