Ho un errore di runtime che si verifica nel rtl Streaming di un modulo, causando un'eccezione EClassNotFound da sollevare mentre si esegue TReader.ReadRootComponent. Il particolare messaggio di errore è "Class not found TActionList".Cosa fa un EClassNotFound generato in fase di runtime significa veramente quando la classe in questione è presente al momento della compilazione e del collegamento, e c'è esplicitamente nel codice?
Che cosa è dispari è:
- La mia forma principale utilizza nell'elenco Azione.
- Per divertimento, ho aggiunto ActnList.pas (dalla cartella di origine VCL) al mio progetto, per provare a risolverlo.
Questo capita a me quando istanziare un modulo che ho lavorato fino a pochi minuti fa. La modifica che ho apportato era in qualche codice sub-frame: ho rimosso tutto il suo codice di sezione di implementazione con un marcatore ifdef, perché sto prendendo in giro alcuni frame, per test delle unità e prototipi.
Ho provato ad aggiungere la classe dell'elenco di azioni al progetto e ho provato con e senza varie opzioni di compilatore e collegamento e tuttavia ho ancora questa eccezione. Ovviamente qualcosa di strano è attivo. Ci deve essere un altro modo strano per ottenere questo problema.
In effetti, sembra che ci sia qualcosa di veramente strano in corso. Quando questo errore viene generato, ottengo il seguente stack di chiamate:
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)
Sembra che il nil è intenzionale, in TReader.ReadDataInner (istanza: TComponent):
while not EndOfList do ReadComponent(nil);
Aggiornamento: Credo la risposta a questa domanda è comprendere i "contesti di serializzazione" come menzionato da Mason. Ed è tempo di ammettere la mia Stupidità: ho rimosso il genitore del frame dal progetto, non rendendomi conto che era il genitore dell'inquadratura. Ho risolto il problema perdendo la dichiarazione del tipo per TMyFrameParent
come TMyFrameParent = class(TFrame)
e questo a sua volta ha portato alla condizione in questione. Lascio la domanda qui perché penso che potrebbe essere davvero utile in futuro notare quando questa eccezione si verifica in casi arcani e come risolverlo. In particolare, Mason ha un po 'di informazioni interessanti sui "contesti di serializzazione" e su come si applicano alla ricerca del nome di classe.
L'nil segnala a ReadComponent solo l'istanza di una nuova istanza anziché la lettura in una esistente. –