У меня ошибка времени выполнения, возникающая в потоковой передаче rtl формы, приводящая к возникновению исключения EClassNotFound при выполнении TReader.ReadRootComponent. Конкретное сообщение об ошибке: «Класс не найден TActionList».
Что странно:
- Моя основная форма использует список действий.
- Ради интереса я добавил ActnList.pas (из папки с исходным кодом VCL) в свой проект, чтобы попытаться это исправить.
Это случается со мной, когда я создаю экземпляр формы, с которой работал несколько минут назад. Внесенные мною изменения были внесены в некоторый код подкадра: я удалил весь код раздела его реализации с маркером ifdef, потому что я макетирую некоторые кадры для модульного тестирования и прототипов.
Я пытался добавить класс списка действий в проект, и я пробовал с различными вариантами компилятора и ссылок и без них, и все же я все еще получаю это исключение. Очевидно, что-то странное происходит. Должен быть другой странный способ решить эту проблему.
На самом деле, похоже, что-то действительно странное происходит. Когда возникает эта ошибка, я получаю следующий стек вызовов:
rtl.Classes.ClassNotFound('TActionList')
rtl.Classes.TReader.FindComponentClass(???)
rtl.Classes.FindExistingComponent
rtl.Classes.TReader.ReadComponent(nil) /// NIL!? WHAT!!!!!
rtl.Classes.TReader.ReadDataInner(???)
rtl.Classes.TReader.ReadData(???)
rtl.Classes.TComponent.ReadState(???)
vcl.Controls.TControl.ReadState(???)
vcl.Controls.TWinControl.ReadState($60B9CF0)
vcl.Forms.TCustomForm.ReadState(???)
rtl.Classes.TReader.ReadRootComponent($606EB90)
rtl.Classes.TStream.ReadComponent($606EB90)
rtl.Classes.InternalReadComponentRes(???,???,$606EB90)
rtl.Classes.InitComponent(TComplexFormContainingFrames)
Кажется, что nil является намеренным, в TReader.ReadDataInner (Instance: TComponent):
while not EndOfList do ReadComponent(nil);
Обновление: Я полагаю, что ответом на этот вопрос является понимание "контекстов сериализации", как упоминал Мейсон. И пришло время признать мою собственную глупость: я удалил родителя фрейма из проекта, не осознавая, что он был родителем фрейма. Я обошел его, пропустив объявление типа для TMyFrameParent
как TMyFrameParent = class(TFrame)
, и это, в свою очередь, привело к рассматриваемому условию. Я оставляю здесь вопрос, потому что думаю, что в будущем было бы очень удобно заметить, когда это исключение возникает в загадочных случаях и как его исправить. В частности, у Мейсона есть действительно интересная информация о «контекстах сериализации» и о том, как они применяются к определению имен классов.