Есть макрос. На уровне BeforeInheritance, я добавляю классу интерфейс и хочу сохранить ссылку или допустим имя класса в списке.
На этапе WithTypedMembers планируется запуск процедуры по завершении обработки последнего класса из списка, полученного на первом этапе.
Вопрос, возможна ли такая схема и как тогда TypeBuilder'а можно получить ссылку на реальный интерфейс?
Здравствуйте, evilbeaver, Вы писали:
E>Есть макрос. На уровне BeforeInheritance, я добавляю классу интерфейс и хочу сохранить ссылку или допустим имя класса в списке. E>На этапе WithTypedMembers планируется запуск процедуры по завершении обработки последнего класса из списка, полученного на первом этапе. E>Вопрос, возможна ли такая схема и как тогда TypeBuilder'а можно получить ссылку на реальный интерфейс?
У TypeBuilder есть свойство UserData, которое можно использовать, например, для хранения вашего списка, а также есть метод InterfacesToImplement(), возвращающий список TypeInfo — интерфейсы.
Здравствуйте, 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();
}
}
}
Здравствуйте, evilbeaver, Вы писали:
E>Возможен ли такой вариант в принципе?
Думаю невозможно он еще не скомпилирован же. Да и зачем? Я так понял вам нужно регистрировать данный тип где-то. Ну и генерируйте код регистрации в какой-то определенный статик метод, а в рантайме его дергайте.
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, evilbeaver, Вы писали:
E>>Возможен ли такой вариант в принципе?
Z>Думаю невозможно он еще не скомпилирован же. Да и зачем? Я так понял вам нужно регистрировать данный тип где-то. Ну и генерируйте код регистрации в какой-то определенный статик метод, а в рантайме его дергайте.
Спасибо за помощь.
Судя по всему я действительно некорректно делаю. Сейчас пробую другйо вариант.
Вроде получилось, но возник такой вопрос:
Во время работы макроса я формирую некоторые объекты, которые в качестве параметра принимают System.Type (так требуется согласно модели)
Собственно я пишу
def cls = SomeCls(@type = Type.GetType(ti.Name))
Но если этот тип принадлежит той же сборке, что и класс, к которому применяется метаатрибут, то я естественно получаю null в параметре @type.
Как я понимаю, такой способ невозможен и мне придется искать другой способ (например не System.Type использовать, а string)?
Здравствуйте, evilbeaver, Вы писали:
E>Вроде получилось, но возник такой вопрос: E>Во время работы макроса я формирую некоторые объекты, которые в качестве параметра принимают System.Type (так требуется согласно модели)
E>Собственно я пишу E>
E>Но если этот тип принадлежит той же сборке, что и класс, к которому применяется метаатрибут, то я естественно получаю null в параметре @type. E>Как я понимаю, такой способ невозможен и мне придется искать другой способ (например не System.Type использовать, а string)?
Вообще не работайте с System.Type — это очень нехорошая практика.
Я же вам указывал на метод тайп билдера — InterfacesToImplement() — который возвращает список интерфейсов (в виде TypeInfo), заявленных для реализации в этом типе.
Здравствуйте, hardcase, Вы писали:
H>Здравствуйте, evilbeaver, Вы писали:
H>Вообще не работайте с System.Type — это очень нехорошая практика. H>Я же вам указывал на метод тайп билдера — InterfacesToImplement() — который возвращает список интерфейсов (в виде TypeInfo), заявленных для реализации в этом типе.
Мы похоже о разных вещах говорим.
От идеи реализации интерфейса я уже отказался. Вся работа делается в момент компиляции и смысла в интерфейсе нет (просто я разбирался в устройстве и работе макросов на примере Serializable-макроса и смотрел результат рефлектором). Поэтому мне кажется, что метод InterfacesToImplement() мне особо не поможет.
А System.Type мне нужен вот почему. Данный класс затем будет использоваться в маппере, который в зависимости от типа будет возвращать тот или иной результат. Маппер подключается через IoC и про немерл может не знать в принципе, поэтому емунужно передать универсальную структуру, описывающую тип (коей и является System.Type).
Работа с типами полей ведется таким образом:
Все "мои" классы я обрабатываю "по-особому".
У всех полей с типом int, string и так далее беру их System.Type (что никоим образом не запрещено).
На все "левые" ругаюсь как и должно быть.
Но в случае enum'ов (которые вроде как тоже скалярные по сути своей) я получаю ошибку. На данный момент я решил проблему таким образом: вставил еще один образец в матч если "enum, то получаем не его тип, а тип его value__".
Здравствуйте, 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 у много чего в макросах).
Пока нет времени протестировать. Это позволит пуроститть собирание статистики и ее последующую обработку.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, evilbeaver, Вы писали:
E>Во время работы макроса я формирую некоторые объекты, которые в качестве параметра принимают System.Type (так требуется согласно модели)
E>Собственно я пишу E>
E>Но если этот тип принадлежит той же сборке, что и класс, к которому применяется метаатрибут, то я естественно получаю null в параметре @type. E>Как я понимаю, такой способ невозможен и мне придется искать другой способ (например не System.Type использовать, а string)?
Вот по этому и не надо использовать System.Type. В немерле типы представляются типами FixedType и TypeVar. Вот ими и нужно оперировать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, 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 для типа объявленного в компилируемой сборке.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.