Ссылка на класс как свойство

Google бесполезен для таких поисков, потому что вы получаете сотни миллионов результатов, абсолютно ни один из которых не относится к конкретному вопросу.

Вопрос просто в следующем:

  • Возможно ли иметь свойство ссылки на класс в Delphi?
  • Если да, то как?

Вот что я пробовал...

type

  TMyObject = class
    // ...
  end;

  TMyObjectClass = class of TMyObject

  TMyObjectA = class(TMyObject)
    // specifics here
  end;

  TMyObjectB  =class(TMyObject)
    // specifics here
  end;

  TMyComponent = class(TComponent)
  private
    FObjectType: TMyObjectClass;
  published
    property ObjectType: TMyObjectClass read FObjectType write FObjectType;
  end;

Приведенный выше код компилируется нормально, однако инспектор объектов вообще не показывает свойство ObjectType.

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

Я хочу сделать это таким образом, чтобы компоненту не нужно было напрямую знать о подклассах (он должен быть полностью модульным).

Позвольте мне пояснить: Я не могу использовать Enum для выбора между типами подклассов, поскольку компонент не может напрямую ссылаться на типы подклассов (Это просто невозможно в этом частный случай)

В любом случае... заранее спасибо!


person LaKraven    schedule 28.01.2012    source источник
comment
Инспектор объектов не показывает свойство, так как для него нет зарегистрированного редактора свойств.   -  person kludg    schedule 28.01.2012


Ответы (2)


Вы можете найти все классы, происходящие от определенного базового класса: base-class">Delphi: во время выполнения найти классы, которые происходят от данного базового класса? и сделать это специальным свойством со списком значений, используя TPropertyEditor.

person Pol    schedule 28.01.2012
comment
Отметил ваш ответ как правильный, поскольку вы ответили первым (и это, конечно, правильный ответ). Я не буду использовать этот метод, потому что не хочу использовать RTTI в этой системе. Решил воспользоваться идеей перекрестно связанных компонентов (где компонент TMyObjectA или TMyObjectB связывается с экземпляром TMyComponent через свойство. Так проще! - person LaKraven; 28.01.2012
comment
Саймон, подумайте, как такой редактор свойств мог бы получить типы классов в контексте пакета времени разработки. - person David Heffernan; 28.01.2012
comment
Дэвид, да... было бы относительно легко (используя RTTI) добавить редактор свойств для обработки такого рода вещей... но, как я сказал в своем предыдущем комментарии, я не хочу использовать RTTI в скомпилированном исполняемый файл (что мне нужно сделать, чтобы получить класс из его квалифицированного имени, хранящегося в DFM) - person LaKraven; 28.01.2012
comment
@LaKraven Нет, это будет нелегко. Вам придется проанализировать исходный код проекта, загруженного в настоящее время в IDE! Помните, что типы классов на самом деле не существуют до времени выполнения, но ваш пакет IDE запускается во время разработки. - person David Heffernan; 28.01.2012
comment
@DavidHeffernan Когда вы устанавливаете пакет в IDE, расширенный RTTI в Delphi 2010 и более поздних версиях может затем проанализировать все классы, определенные в нем. Таким образом, любой экземпляр компонента в этом пакете, который имеет свойство ссылки на класс, будет (при условии существования редактора свойств для его обработки) работать просто отлично! - person LaKraven; 28.01.2012
comment
@LaKraven Хорошо, но я предполагаю, что вы действительно захотите сослаться на классы, которые не были установлены в IDE. Как насчет класса, определенного в Unit1.pas в вашем приложении VCL? Вы хотите ссылаться только на классы VCL? - person David Heffernan; 28.01.2012
comment
Дэвид, это тоже работает! Загрузите любой проект в IDE, и RTTI сможет увидеть все типы, определенные в нем во время разработки. Именно так работает мой генератор модулей оболочки Lua4Delphi... так что я уже использую эту возможность! - person LaKraven; 28.01.2012
comment
Действительно? Он может видеть типы в исходном коде, которого нет в пакете времени разработки? - person David Heffernan; 28.01.2012
comment
Давид, да! Я думаю, что с D2010 они использовали RTTI, по крайней мере, для поддержки таких вещей, как завершение кода и моделирование UML... в любом случае, RTTI может проводить самоанализ всех типов, определенных в рамках чего-либо активного внутри IDE... включая активный проекты! - person LaKraven; 28.01.2012
comment
Если вы хотите создать PropertyEditor для этого свойства, измените его тип на тип string, потому что TMyObjectClass не имеет информации о типе. - person NGLN; 29.01.2012
comment
@LaKraven: Это обсуждение изучения типов, объявленных в любом Unit1.pas или другом файле проекта, интригует, но пока я не могу его воспроизвести. Кто-нибудь хочет рассказать мне, как это работает, ответив на этот вопрос. stackoverflow .com/questions/9057312/ - person LachlanG; 30.01.2012
comment
Чтобы прояснить вышеизложенное... оказывается, я полностью ошибался, а @DavidHeffernan был прав! RTTI нельзя использовать во время разработки для самоанализа типов, определенных в активном проекте. Он может делать это только для типов, зарегистрированных в пакете! - person LaKraven; 31.01.2012

Если вы собираетесь это сделать, вам потребуется предоставить редактор свойств. IDE не поставляется с редакторами свойств для свойств типа класса. Вам также потребуется обработать постоянство .dfm. Вы должны записать тип класса в файл .dfm в виде строки, и когда файл .dfm будет прочитан, вам нужно будет исправить ссылку. Новый стиль RTTI может сделать это.

Однако я не думаю, что все это на самом деле жизнеспособно по следующей причине. Ваш код времени разработки выполняется в пакете внутри IDE и не имеет доступа к типам классов в активном проекте в IDE. Эти типы классов существуют только при запуске этого проекта. Таким образом, свойство ObjectType в коде в вашем вопросе не может быть назначено чему-либо значимому в пакете времени разработки. Что ж, вы можете использовать его для классов, определенных в VCL, и любых других пакетах, установленных в вашей среде IDE, но я скорее предполагаю, что вы захотите использовать его для классов, определенных в активном проекте.

Я думаю, все это означает, что вместо этого вы должны использовать простое строковое свойство и исправлять ссылки на типы классов только во время выполнения.

person David Heffernan    schedule 28.01.2012