Ещё вопрос по макросам - как удалить атрибуты?
От: SergASh  
Дата: 02.10.07 20:10
Оценка:
Привет всем!

Как можно из кода макроса уровня класса удалить некоторые атрибуты (не макро-, а обычные), заданные для целевого класса?

Дело в том, что для настройки работы моего макроатрибута нужно передать довольно много информации, точнее много наборов почти однотипных данных. Кажется естественным передавать их через атрибуты — так код легче читать, чем если всё передавать через параметры макроса. Вот пример (без особого смысла, но идею иллюстрирует)
  [Wrapper] // Это макрос. Остальное - обычные атрибуты
  [WrapperField( Name = "order_line_id", TypeName = "long", IsKey = true, IsAutoKey = true )]
  [WrapperKey( IsAuto = false )]
  [WrapperField( Name = "order_id", TypeName = "long", IsKey = true, IsAutoKey = false )]
  [WrapperKey( IsAuto = true )]
  [WrapperField( Name = "order_name", TypeName = "string", IsKey = true, IsAutoKey = true )]
  [WrapperField( Name = "order_desc", TypeName = "string", IsKey = true )]
  [WrapperField( Name = "order_date", TypeName = "DateTime", IsKey = true, IsAutoKey = true )]
  [WrapperField( Name = "is_confirmed", TypeName = "bool" )]
  [WrapperField( Name = "session_id", TypeName = "long", IsKey = true, IsAutoKey = false )]
  [WrapperField( Name = "session_name", TypeName = "string", IsKey = true, IsAutoKey = false )]
  public class OrderEntity
  {
  }

Всё работает нормально, но есть две проблемы. Во-первых, для каждого вида атрибутов надо написать класс, а это делать лень, поскольку всё равно после компиляции атрибут ни для чего не используется. И к тому же при добавлении новых свойств в атрибут его код придётся изменять. А если из объявлений все упоминания об атрибуте поудалять, то есть надежда, что компилятор не станет его искать класс. Во-вторых, в конце концов мой класс оказывается помечен десятками экземпляров одного и того же атрибута. Как-то это бестолково, вот и хочется лишние атрибуты выбросить.

Спасибо.
Re: Ещё вопрос по макросам - как удалить атрибуты?
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.10.07 14:29
Оценка:
Здравствуйте, SergASh, Вы писали:

А почему бы просто не оформить их метаатрибутами? Прямо в них винимать информацию, разбирать и помещать в удобном виде куда нужно...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Ещё вопрос по макросам - как удалить атрибуты?
От: SergASh  
Дата: 03.10.07 15:50
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А почему бы просто не оформить их метаатрибутами? Прямо в них винимать информацию, разбирать и помещать в удобном виде куда нужно...


А как тогда быть с порядком обработки? Если макроатрибуты обрабатываются в порядке объявления, что ещё нужно проверить, то тогда главный макрос надо будет писать последним. Как-то это неестественно, всё равно что имя метода писать после его тела.

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

К тому же код усложнится — придётся хранить соответствие между TypeBuilder'ом и наборами данных до того момента когда эти данные понадобятся основному макросу, потому что никто не гарантирует порядок обработки метаатрибутов для разных классов. Хотя здесь я могу и ошибаться.

В общем, похоже это только усложнит жизнь.

PS. Влад, когда же Вы наконец выложите продолжение статьи про макросы, а то в наших краях RSDN Magazine не сыщешь.
Re[3]: Ещё вопрос по макросам - как удалить атрибуты?
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.10.07 08:08
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>А как тогда быть с порядком обработки?


Накапливашь информацию в неком объекте, а птом, на следующей стадии обработки макросов, обрабатываешь ее за один прием.

SAS>Плюс это не решает вторую проблему — если ничего не изменилось в последних версиях, то метаатрибуты с параметрами превращаются в обычные атрибуты после компиляции.


Метаатрибуты (насколько я помню) просто удаляются после того как они обработаны.

Что касается удаления атрибутов, то сейчас сказать ничего не могу. Нужно смореть как там все устроено. По позже попытаюсь поглядеть. Но по мне так это не очень верный подход. Удалять что-то — это не выход. Такой подход череват ошибками. Ведь теряется история. Лучше всегда что-то порождать или выполнять, а не удалять.

SAS>PS. Влад, когда же Вы наконец выложите продолжение статьи про макросы, а то в наших краях RSDN Magazine не сыщешь.


Статьи выкладываются через 1-3 месяца после выхода. Точный срок зависит от фазы луны (просто статьи из номера выкладываются по одной, чтобы распределить их появление во внемени).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Оказывается можно
От: SergASh  
Дата: 12.10.07 17:09
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Что касается удаления атрибутов, то сейчас сказать ничего не могу. Нужно смореть как там все устроено. По позже попытаюсь поглядеть. Но по мне так это не очень верный подход. Удалять что-то — это не выход. Такой подход череват ошибками. Ведь теряется история. Лучше всегда что-то порождать или выполнять, а не удалять.


Метод Modifiers.GetCustomAttributes() просто возвращает значение поля custom_attrs, которое mutable и public. Да здравствует инкапсуляция! Не знаю, долго ли ещё это поле будет оставаться открытым, но пока его можно изменить отфильтровав ненужные атрибуты.

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

А во-вторых, и для меня это намного важнее, можно достичь полезного эффекта. Если я генерирую поля со значениями по умолчанию и хочу эти значения указывать через свойства атрибута, то выходит, что в зависимости от типа поля тип выражения, задающего умолчание, будет отличаться. Например
[GenFld( Name="firstName", TypeName="string", Default="John" )]
[GenFld( Name="age", TypeName="long", Default=28 )]

Ясно, что имея нормальный атрибут я бы не смог такое написать, потому что свойство Default должно быть какого-то одного типа. А так, до тех пор, пока я использую только AST для значения Default и не пытаюсь вычленить литерал или ещё что-то, всё отлично работает, что мне и нужно. Можно даже написать Default = 1 + 2 или Default = 1.2 :> long, так тоже работает.

VD>Метаатрибуты (насколько я помню) просто удаляются после того как они обработаны.


У меня один раз получилось так, что метаатрибут с параметрами был преобразован в обычный, только имя было дополнено названием фазы. Наверное, это в какой-то версии убрали — сейчас так не получается.
Re[5]: Оказывается можно
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.10.07 06:01
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Метод Modifiers.GetCustomAttributes() просто возвращает значение поля custom_attrs, которое mutable и public. Да здравствует инкапсуляция! Не знаю, долго ли ещё это поле будет оставаться открытым, но пока его можно изменить отфильтровав ненужные атрибуты.


По уму надо бы закрыть. Если нужно менять список атрубуто, то надо делать это через явный АПИ.

SAS>На счёт зачем, во-первых, если все вхождения некоторого атрибута удалить из всех классов, то компилятор действительно не пытается его найти, поэтому и определять класс атрибута не нужно. И вероятность ошибки уменьшается таким образом, потому что остаётся только одно место, где используются свойства атрибута, вместо двух.


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

SAS>А во-вторых, и для меня это намного важнее, можно достичь полезного эффекта. Если я генерирую поля со значениями по умолчанию и хочу эти значения указывать через свойства атрибута, то выходит, что в зависимости от типа поля тип выражения, задающего умолчание, будет отличаться. Например

SAS>
SAS>[GenFld( Name="firstName", TypeName="string", Default="John" )]
SAS>[GenFld( Name="age", TypeName="long", Default=28 )]
SAS>

SAS>Ясно, что имея нормальный атрибут я бы не смог такое написать, потому что свойство Default должно быть какого-то одного типа.

А что в дотнете уже отменили object?

SAS>У меня один раз получилось так, что метаатрибут с параметрами был преобразован в обычный, только имя было дополнено названием фазы. Наверное, это в какой-то версии убрали — сейчас так не получается.


Я такого даже видел.

Удаление атрибутов — это своеобразный хак. А я хаки стараюсь избегать. От них всегда уши вылезают.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.