Опасны ли пользовательские атрибуты для Enums? - PullRequest
25 голосов
/ 07 марта 2012

Я создаю приложение, которое интенсивно использует Enum s для пользовательских данных. По сути, объект хранится в базе данных с около 28 отдельными атрибутами. Каждый атрибут представляет собой двухсимвольное поле, которое переводится из SQL прямо в Enum.

К сожалению, мне нужно также перевести эти значения в два различных понятных человеку значения. Один - для легенды в таблице данных, а другой - для класса CSS для стилизации изображения в интерфейсе веб-приложения.

Для этого я настроил два пользовательских атрибута и применил их к Enum, где это необходимо. Например:

Интерфейс пользовательских атрибутов

public interface IAttribute<T>
{
    T Value { get; }
}

Пример пользовательского атрибута

public sealed class AbbreviationAttribute: Attribute, IAttribute<string>
{
    private readonly string value;

    public AbbreviationAttribute(string value)
    {
        this.value = value;
    }

    public string Value
    {
        get { return this.value; }
    }
}

Метод получения пользовательского атрибута из Enum

public static R GetAttributeValue<T, R>(IConvertible @enum)
{
    R attributeValue = default(R);

    if (@enum != null)
    {
        FieldInfo fi = @enum.GetType().GetField(@enum.ToString());

        if (fi != null)
        {
            T[] attributes = fi.GetCustomAttributes(typeof(T), false) as T[];

            if (attributes != null && attributes.Length > 0)
            {
                IAttribute<R> attribute = attributes[0] as IAttribute<R>;

                if (attribute != null)
                {
                    attributeValue = attribute.Value;
                }
            }
        }
    }

    return attributeValue;
}

Пример Enum Использование этого шаблона

public enum Download
{
    [Abbreviation("check")]
    [Description("Certified")]
    C = 1,

    [Abbreviation("no-formal")]
    [Description("No formal certification")]
    NF = 2,

    [Abbreviation("cert-prob")]
    [Description("Certified with potential problems")]
    CP = 3
}

И Abbreviation, и Description являются пользовательскими атрибутами, которые реализуют IAttribute<T>. У моего фактического Enum есть 11 возможных значений, и, как я упоминал ранее, он используется в 28 отдельных свойствах моего пользовательского объекта. Использование пользовательских атрибутов казалось лучшим способом отобразить эту информацию туда и обратно.

Теперь на вопрос, это лучший способ сделать это? Я сохраняю значение Enum ("C", "NF" или "CP" в фрагменте выше) в базы данных, но мне нужны значения аббревиатуры и описания в моем коде. Кроме того, я сомневаюсь, что это будет последний набор пользовательских атрибутов, которые мне понадобятся.

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

Ответы [ 3 ]

15 голосов
/ 07 марта 2012

Это тот же метод, который я использую. Единственным недостатком является сериализация. Значения пользовательских атрибутов не сериализуются.

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

2 голосов
/ 07 марта 2012

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

class SpecialType {
  // include the fields and all attributes that you need to reference, ToString method for debugging, and any serialization you need
  public string foo { get; set; }
  public string bar { get; set; }
  public ToString() { return "SpecialType with foo '" + foo + "' and bar '" + bar + "'"; }
}

Dictionary<int, SpecialType> myDict = new Dictionary<int, SpecialType> {
   { 1, new SpecialType { foo = "XA1B2", bar = "XC3D4" } },
   { 2, new SpecialType { foo = "ZA1B2", bar = "ZC3D4" } },
   { 3, new SpecialType { foo = "YA1B2", bar = "YC3D4" } },
}

Тогда я мог бы легко хранить целые числа в других моих классах, чтобы сохранить память, выяснить, было ли определенное значение допустимым, проверив наличие в ключах словаря, всего этого джаза. Вероятно, было бы намного проще выполнить привязку данных, если вы в конечном итоге тоже собираетесь использовать WPF или чтение / запись на диск.

1 голос
/ 07 марта 2012

Можете ли вы изменить базу данных? Я думаю, что лучшим вариантом было бы создать таблицу (или таблицы) для размещения возможных значений перечислений и внешнего ключа основных объектов (вместо использования кодов символов - это упрощает перенос и нормализует вашу БД) , Задайте для таблицы столбцы Abbreviation и Description, затем извлеките их и свяжите с ними по их ключу, а затем кэшируйте, если поиск выполняется медленно.

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

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