Pull to refresh

Comments 14

Спасибо! Мне тоже кажется работа с «enum + аттрибуты» часто более удобной.

> Я бы выделил несколько причин, по которым считаю этот подход неудачным:
Я бы добавил к минусам следующее:
strQuery += "DateFrom >= '" + DateFromValue.ToString() + "'";
С immutable-классами так работать нельзя. Здесь лучше использовать StringBuilder и string.Format("",...).

А в плюсы энумок добавил бы упрощение локализации через аттрибуты. К примеру, можно для значений указать аттрибуты вида «LocalizableFriendlyName» и через extension-methods возвращать для конкретного значения перечисления локализованное дружественное имя и какого-либо ресурса.
>С immutable-классами так работать нельзя. Здесь лучше использовать StringBuilder и string.Format("",...).
наверное так будет лучше, ну сути это не меняет.
Мне кажется, уже есть стандартный для вашего случая формат метаданных — Expressions. И с помощью PredicateBuilder легко получить такие «собираемые предикаты» и потом на этот полученный Expression можно скормит Entity Framework, LINQ, или даже для некоторого несложного подмножества написать свою реализацию репозитория, разбирающего выражение и делая запрос на основе него к произвольному хранилищу.
Да, еще бывают Expression. В следующий раз попробую воспользоваться ими. Данное решение получилось путем эволюционного перехода от констант и показалось мне интересным.
Лишние переносы строк в примерах кода уберите, пожалуйста.
Вы знаете, в тексте нет переносов. Предпросмотр перед публикацией показывал тексты нормально, а после публикации — выглядит вот так странно. Как бороться, к сожалению, не знаю, но буду благодарен за любой совет.
Справился с оформлением кода. Оказывается хабр умеет сам подсвечивать исходники, однако это не сразу найдешь.
У вас есть конкретный enum DGA, к которому вы добавили конкретные extensions DGAExt. Зачем использовать медленный reflection, когда можно было просто сделать в классе DGAExt
private Dictionary<DGA, string> attributeNames = new Dictionary<DGA, string>
{
{ DGA.RegDate, «doc_RegCard/rc_Index/date_Дата_регистрации» },
{ DGA.RegNum, «doc_RegCard/rc_Index/text_Регистрационный_номер» },

};

public static string GetAttribName(this DGA attrib)
{
return this.attributeNames[ attrib ];
}

Либо вообще сделать attributeNames public и обойтись без метода, хотя метод позволяет добавить валидацию в случае необходимости.

Без reflection скорость выше, понятность в худшую сторону не меняется, весь мэппинг аналогично находится в одном месте, просто не в декларации самого enum.
Да, наверное в случае когда нужно привесить одну строку такой вариант можно использовать.
Разница, наверное, не столько в читаемости, сколько в гарантии неизменности словаря.
Хотя был случай, когда я как раз такой словарь и использовал, а наполнялся он в процессе работы программы.

Насчет производительности ничего не могу сказать, но я не думаю, что конкретно в этом случае reflection сильно медленнее словаря, надо будет померять при случае.
Почему «привесить одну строку»? Как ваш атрибут можно расширять свойствами, так и мэппинг можно делать не в строку, а в сложный класс, имеющий все небходимые свойства, либо делать набор мэппингов — по вкусу.
Что касается неизменяемости словаря, что вас смущает, если он скрыт, а доступ организован через метод?
*Долго думал
Давайте чуть-чуть проанализируем.
Чем плохо использование атрибутов по сравнению со словарем?
Судя по всему — только производительностью

Чем плохо использование словаря по сравнению с атрибутами?
На этот вопрос я долго не мог ответить даже для себя. Было только подсознательное ощущение какой-то неправильности. Наконец осознал. Проблема чисто организационная — информация о присоединенных атрибутах находится в стороне от объявления элементов перечисления. Таким образом, если когда кто-то будет добавлять элементы перечисления, то он может не сходу увидеть, что атрибуты добавляются где-то еще. Т.е. имеет место небольшое нарушение принципа DRY: каждый элемент перечисления нужно продублировать в инициализаторе словаря.

Вариант решения
В итоге мне кажется разумным использовать комбинированный вариант, а именно, писать метаданные в атрибуты, но завести словарь, информация в который загружается в процессе выполнения(например, в статическом конструкторе класса-расширения). Это обеспечит нужную производительность и сохранит прозрачность кода.
Да, вариант кэширования в мэппинге хорош, я об этом уже тоже думал.
Sign up to leave a comment.

Articles