EClassNotFound在运行时引发的内容真正意味着当有问题的类在编译和链接时出现时,代码中是否有明确的含义?

War*_* P 7 delphi exception object-persistence delphi-xe

我在表单的rtl Streaming中发生运行时错误,导致在执行TReader.ReadRootComponent时引发异常EClassNotFound.特定错误消息是"Class not found TActionList".

奇怪的是:

  1. 我的主要表单使用动作列表.
  2. 为了好玩,我将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)
Run Code Online (Sandbox Code Playgroud)

似乎nil是故意的,在TReader.ReadDataInner(Instance:TComponent)中:

      while not EndOfList do ReadComponent(nil);
Run Code Online (Sandbox Code Playgroud)

更新:我相信这个问题的答案是理解梅森提到的"序列化背景".并且,是时候承认我自己的愚蠢:我从项目中删除了框架的父级,没有意识到它是框架的父级.我通过将类型声明存根为TMyFrameParentas TMyFrameParent = class(TFrame)来解决这个问题,这反过来会导致问题.我在这里留下这个问题是因为我认为将来可能会非常方便地注意到这种异常发生在神秘的情况下,以及如何解决它.特别是,Mason有一些关于"序列化上下文"以及它们如何应用于类名查找的非常有趣的信息.

Mas*_*ler 8

这意味着在当前的反序列化上下文中找不到该类.并非所有现有类都已注册所有加载.每个表单类都有RTTI,其中包含对其使用的组件的引用.要使其工作,请确保您的表单(或框架,如果这是一个框架)在私有标记之前声明至少一个TActionList :

TMyForm = class(TForm)
  ActionList: TActionList;
  OtherComponent: TSomeComponent;
private
  //whatever
public
  //whatever
end;
Run Code Online (Sandbox Code Playgroud)