Еще один вопрос по макросам
От: evilbeaver  
Дата: 12.04.10 07:07
Оценка:
Есть макрос. На уровне BeforeInheritance, я добавляю классу интерфейс и хочу сохранить ссылку или допустим имя класса в списке.
На этапе WithTypedMembers планируется запуск процедуры по завершении обработки последнего класса из списка, полученного на первом этапе.
Вопрос, возможна ли такая схема и как тогда TypeBuilder'а можно получить ссылку на реальный интерфейс?
Re: Еще один вопрос по макросам
От: hardcase Пират http://nemerle.org
Дата: 12.04.10 07:31
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Есть макрос. На уровне BeforeInheritance, я добавляю классу интерфейс и хочу сохранить ссылку или допустим имя класса в списке.

E>На этапе WithTypedMembers планируется запуск процедуры по завершении обработки последнего класса из списка, полученного на первом этапе.
E>Вопрос, возможна ли такая схема и как тогда TypeBuilder'а можно получить ссылку на реальный интерфейс?

У TypeBuilder есть свойство UserData, которое можно использовать, например, для хранения вашего списка, а также есть метод InterfacesToImplement(), возвращающий список TypeInfo — интерфейсы.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: Еще один вопрос по макросам
От: evilbeaver  
Дата: 12.04.10 07:53
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, evilbeaver, Вы писали:


E>>Есть макрос. На уровне BeforeInheritance, я добавляю классу интерфейс и хочу сохранить ссылку или допустим имя класса в списке.

E>>На этапе WithTypedMembers планируется запуск процедуры по завершении обработки последнего класса из списка, полученного на первом этапе.
E>>Вопрос, возможна ли такая схема и как тогда TypeBuilder'а можно получить ссылку на реальный интерфейс?

H>У TypeBuilder есть свойство UserData, которое можно использовать, например, для хранения вашего списка, а также есть метод InterfacesToImplement(), возвращающий список TypeInfo — интерфейсы.


Возможно я неправильно сформулировал. В общем цель такая.
Есть такой интерфейс
interface ISome
{
   method():void
}


Есть некий объект (синглтон), хранящий список тайпбилдеров классов, для которых указан данный атрибут, допустим SomeList
class SomeList
{
  ...
  [Accessor]
  mutable typeBuilders:list[TypeBuilder];
  // метод добавляет тайпбиледр в список
  Add(t:TypeBuilder):void { ... }
  // метод делает на то, что данный класс последний
  CheckIfLast(t:TypeBuilder):bool { ...}
  ...
}


Вот макрос BeforeInheritance

[MacroUsage (MacroPhase.BeforeInheritance, MacroTargets.Class,
                     Inherited = true)]
macro SomeMacro (t : TypeBuilder){
  t.AddImplementedInterface (<[ ISome ]>);
  // здесь мы фиксируем список классов, к которым применен атрибут
  // по окончании этой стадии список будет окончательно сформирован
  SomeList.Add(t);
}


Вот макрос WithTypedMembers
 [MacroUsage (MacroPhase.WithTypedMembers, MacroTargets.Class,
                       Inherited = true)]
  macro SomeMacro (t : TypeBuilder){
  ...
      t.Define (<[ decl: public method () : void
                     implements ISome.method {
                       .. $statements
                     }
            ]>);
  when(SomeList.Instance.CheckIfLast(t))
  {
     foreach(tb in SomeList.Instance.TypeBuilders)
     {
        // вот здесь бы неплохо вызывать тот самый method
        // только я не знаю как из TypeBuilder'а получить ссылку на ISome
        (???tb???).method();
     }
  }
  }


Возможен ли такой вариант в принципе?
Re[3]: Еще один вопрос по макросам
От: Ziaw Россия  
Дата: 12.04.10 08:17
Оценка: +1
Здравствуйте, evilbeaver, Вы писали:

E>Возможен ли такой вариант в принципе?


Думаю невозможно он еще не скомпилирован же. Да и зачем? Я так понял вам нужно регистрировать данный тип где-то. Ну и генерируйте код регистрации в какой-то определенный статик метод, а в рантайме его дергайте.
Re[4]: Еще один вопрос по макросам
От: evilbeaver  
Дата: 12.04.10 08:34
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Здравствуйте, evilbeaver, Вы писали:


E>>Возможен ли такой вариант в принципе?


Z>Думаю невозможно он еще не скомпилирован же. Да и зачем? Я так понял вам нужно регистрировать данный тип где-то. Ну и генерируйте код регистрации в какой-то определенный статик метод, а в рантайме его дергайте.


Спасибо за помощь.
Судя по всему я действительно некорректно делаю. Сейчас пробую другйо вариант.
Re[4]: Еще один вопрос по макросам
От: evilbeaver  
Дата: 12.04.10 08:46
Оценка:
Вроде получилось, но возник такой вопрос:
Во время работы макроса я формирую некоторые объекты, которые в качестве параметра принимают System.Type (так требуется согласно модели)

Собственно я пишу
def cls = SomeCls(@type = Type.GetType(ti.Name))


Но если этот тип принадлежит той же сборке, что и класс, к которому применяется метаатрибут, то я естественно получаю null в параметре @type.
Как я понимаю, такой способ невозможен и мне придется искать другой способ (например не System.Type использовать, а string)?
Re[5]: Еще один вопрос по макросам
От: hardcase Пират http://nemerle.org
Дата: 12.04.10 09:01
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Вроде получилось, но возник такой вопрос:

E>Во время работы макроса я формирую некоторые объекты, которые в качестве параметра принимают System.Type (так требуется согласно модели)

E>Собственно я пишу

E>
E>def cls = SomeCls(@type = Type.GetType(ti.Name))
E>


E>Но если этот тип принадлежит той же сборке, что и класс, к которому применяется метаатрибут, то я естественно получаю null в параметре @type.

E>Как я понимаю, такой способ невозможен и мне придется искать другой способ (например не System.Type использовать, а string)?

Вообще не работайте с System.Type — это очень нехорошая практика.
Я же вам указывал на метод тайп билдера — InterfacesToImplement() — который возвращает список интерфейсов (в виде TypeInfo), заявленных для реализации в этом типе.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: Еще один вопрос по макросам
От: evilbeaver  
Дата: 12.04.10 09:38
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, evilbeaver, Вы писали:


H>Вообще не работайте с System.Type — это очень нехорошая практика.

H>Я же вам указывал на метод тайп билдера — InterfacesToImplement() — который возвращает список интерфейсов (в виде TypeInfo), заявленных для реализации в этом типе.

Мы похоже о разных вещах говорим.
От идеи реализации интерфейса я уже отказался. Вся работа делается в момент компиляции и смысла в интерфейсе нет (просто я разбирался в устройстве и работе макросов на примере Serializable-макроса и смотрел результат рефлектором). Поэтому мне кажется, что метод InterfacesToImplement() мне особо не поможет.
А System.Type мне нужен вот почему. Данный класс затем будет использоваться в маппере, который в зависимости от типа будет возвращать тот или иной результат. Маппер подключается через IoC и про немерл может не знать в принципе, поэтому емунужно передать универсальную структуру, описывающую тип (коей и является System.Type).
Работа с типами полей ведется таким образом:
Все "мои" классы я обрабатываю "по-особому".
У всех полей с типом int, string и так далее беру их System.Type (что никоим образом не запрещено).
На все "левые" ругаюсь как и должно быть.

Но в случае enum'ов (которые вроде как тоже скалярные по сути своей) я получаю ошибку. На данный момент я решил проблему таким образом: вставил еще один образец в матч если "enum, то получаем не его тип, а тип его value__".
Re: Еще один вопрос по макросам
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.04.10 19:16
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Есть макрос. На уровне BeforeInheritance, я добавляю классу интерфейс и хочу сохранить ссылку или допустим имя класса в списке.

E>На этапе WithTypedMembers планируется запуск процедуры по завершении обработки последнего класса из списка, полученного на первом этапе.
E>Вопрос, возможна ли такая схема и как тогда TypeBuilder'а можно получить ссылку на реальный интерфейс?

Буквально завтра залью изменения в компиляторе:
1. Появится события:
    public event CompilationStart    : CompilerEventHandler;
    public event TypeTreeBuildFinish : CompilerEventHandler;

и свойство:
    mutable _userData : SC.IDictionary;
    
    public UserData : SC.IDictionary
    {
      get
      {
        when (_userData == null)
          _userData = ListDictionary();
          
        _userData
      }
    }

в ManagerClass (свойство Manager у много чего в макросах).

Пока нет времени протестировать. Это позволит пуроститть собирание статистики и ее последующую обработку.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Еще один вопрос по макросам
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.04.10 19:20
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>Во время работы макроса я формирую некоторые объекты, которые в качестве параметра принимают System.Type (так требуется согласно модели)


E>Собственно я пишу

E>
E>def cls = SomeCls(@type = Type.GetType(ti.Name))
E>


E>Но если этот тип принадлежит той же сборке, что и класс, к которому применяется метаатрибут, то я естественно получаю null в параметре @type.

E>Как я понимаю, такой способ невозможен и мне придется искать другой способ (например не System.Type использовать, а string)?

Вот по этому и не надо использовать System.Type. В немерле типы представляются типами FixedType и TypeVar. Вот ими и нужно оперировать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Еще один вопрос по макросам
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.04.10 19:28
Оценка:
Здравствуйте, evilbeaver, Вы писали:

E>А System.Type мне нужен вот почему. Данный класс затем будет использоваться в маппере, который в зависимости от типа будет возвращать тот или иной результат. Маппер подключается через IoC и про немерл может не знать в принципе, поэтому емунужно передать универсальную структуру, описывающую тип (коей и является System.Type).


System.Type нужен в рантайме, а не в макросе? Так?

Вот так вот:
PExpr.Typed(TExpr.TypeOf(typeVar))

или так:
<[ $(TExpr.TypeOf(typeVar) : typed) ]>

можно сформировать код ссылающийся на тип. При этом в сгенерированном коде будет пямая и эффективная ссылка на тип. Прямого аналога в синтаксисе для этого не существует. Ближайшее по смыслу выражение typeof(квалифицированное имя типа).
Здесь "typeVar" = это переменная типа TypeVar или FixedType.

E>Но в случае enum'ов (которые вроде как тоже скалярные по сути своей) я получаю ошибку.


Видимо потому, что пытаешся в макросе получить System.Type для типа объявленного в компилируемой сборке.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.