Атрибуты на самом деле имеют две цели: как видимые пользователю вещи и как вещи, испускаемые компилятором.
Я полагаю, вы говорите о видимых пользователем атрибутах.
В целом, я бы сказал, что видимые пользователю атрибуты не идеальны.
Большую часть времени они используются для встраивания какой-либо формы пользовательского языка поверх C #. Атрибуты DLINQ являются хорошим примером этого. Лучшим подходом, с точки зрения потребителя, было бы добавить первоклассную поддержку к языку хоста. Это будет в конечном итоге чувствовать себя гораздо более естественным. (имея языковую поддержку для определения таблиц и внешних ключей было бы намного легче работать со всеми безумными атрибутами linq-to-sql).
В действительности, однако, расширение языка программирования слишком затратно для большинства разработчиков. Преимущества просто не взвешивают затраты.
Возможно, когда-нибудь в C # появятся функции метапрограммирования, которые упростят такую задачу.
Однако на данный момент такой возможности не существует.
Это оставляет вам 3 варианта:
- Использовать атрибуты
- Использование динамического языка и генерация кода во время выполнения
- Только не используйте генеративное программирование
Обычно № 1 оказывается самым простым выбором, даже если он не идеален.