Ignore unknown properties when reading object from stream
Asked Answered
T

1

6

We have an application that stores project information in a file by descending from TPersistent. We use TSteam.ReadComponentRes to read from a stream to the object.

We would like to be able to open project files with unknown properties (from newer versions or other development branches of our application). Currently this results in an exception in TReader, which is created by TStream. We've considered making a TStream descendant that uses a TReader descendant that handles this exception instead of stopping reading. Can anybody think of a more elegant way of doing this?

Taunyataupe answered 7/6, 2011 at 13:21 Comment(1)
Yes - I would like to know how to do this too. The TReader excepts and I don't know how to 'resume' it. This has caused problems in my 'TpersistentForm' class that streams out all the published properties to a file on destroy and streams them back in again on create. As you say, there are big problems during development where I am adding/deleting controls from the forms :( I have added in serial bodges over the years to get round most of the problems, but I have never been totally happy.Adur
L
9

Call Stream.ReadResHeader, create a TReader instance, set its OnError event and call Reader.ReadRootComponent and free the reader (i.e. mimic the behaviour of TStream.ReadComponentRes).

Inside the OnError event handler you can set handled := true.

Lorca answered 7/6, 2011 at 13:46 Comment(5)
Agreed, use OnError event. Here's an example for DoubleBuffered and ParentDoubleBuffered properties both at runtime and designtime.Bankrupt
This sounds great. I'm having trouble with Reader.OnError:=OnReaderError;. I get a E2009 Incompatible types: 'method pointer and regular procedure' error, though. Got any tips?Taunyataupe
From the error message it appears that you have defined your OnReaderError procedure at the global level (outside a class). Define it within a class and assign the event to the method of an instance of the classRemote
It's going to have to be a procedure of object, just like an event handler. I can use a method of my 'TpersistentForm' class, but not sure about a more general Tpersistent.Adur
Got it: procedure TpersistentContext.DFMreaderError(Reader: TReader; const Message: string; var Handled: Boolean); begin handled:=true; end;Adur

© 2022 - 2024 — McMap. All rights reserved.