How to de-serialize sub-property in delphi?

Since two days ago I started creating my own simple classes from scratch, going down from TObject , nothing unusual. I also needed to write / read them to / from files, so after some searches, because I have not yet studied all the inputs and outputs of serialization and have not fully received them, I borrowed serialization methods from here . It worked fine when I tested it. Then I added another class as a property (which I mean when I say sup-property: class properties, that property in my class ... this is confusing, it needs a proper name), following the advice in this SO question about how to actually do it. Now writing to a file does not seem to cause any errors, then again I am not sure that the sub-properties are spelled correctly or just garbage. However, reading it causes

EPropertyConvertError exception class with the message "Invalid property type: TSomething"

Since I'm just learning this, I'm not sure what is wrong. I have a few guesses, one of which would be that TSomething = Class might need to have its own serialization methods? In that case, how would it work (even if I do not believe this assumption)? Another thing is that the code I borrowed from delphi.about.com cannot handle these properties? And if so, how could I improve it? And if not one of my guesses is true, how can this work be done? (And I'm using DelphiXE2.)

Code on request:

 TSomething = Class protected fNumber: integer; fLine: string; public procedure Assign(Source: TObject); published property Number: integer read fNumber write fNumber; property Line: string read fLine write fLine; End; TOther = Class public procedure LoadFromStream(const Stream: TMemoryStream); procedure SaveToStream(const Stream: TMemoryStream); constructor Create; virtual; destructor Destroy; override; protected fSomething: TSomething; procedure SetfSmth(AValue: TSomething); published property Something: TSomething read fSomething write SetfSomething; end; 

The implementation of the methods was borrowed from the two links that were provided above, I do not see the need to re-specify this, unless requested.

+4
source share
2 answers

To serialize TSomething, it must be a subcomponent. To do this, you need to change one thing: do not derive two classes from TObject, but from TComponent. Then in the TSomething constructor, you call

 Self.SetSubComponent(True); 

FInally, since your class is TComponent, you will no longer need materials taken from delphi. Because TComponent can be directly serialized to TStream using WriteComponent / ReadComponent

You will see that the process is easier when choosing the right child. Here the choice is logical: if you want to serialize, use TComponent.

+3
source

I think you should follow how you yourself can use the serialization methods of the TSomething class.

Here is an example of using XML for serialization:

 TSomething = class(TPersistent) protected FNumber: Integer; FLine: String; public procedure WriteToXmlNode(XmlNode: IXmlNode); procedure ReadFromXmlNode(XmlNode: IXmlNode); published property Number: Integer read FNumber write FNumber; property Line: String read FLine write FLine; end; TOther = class(TPersistent) protected FSomething: TSomething; public procedure WriteToXmlNode(XmlNode: IXmlNode); procedure ReadFromXmlNode(XmlNode: IXmlNode); published property Something: TSomething read FSomething write FSomething; end; 

In other words, letting each of the classes know how to serialize itself into XML.

Then the TOther write method will look like this:

 procedure TOther.WriteToXmlNode(XmlNode: IXmlNode) var ChildNode: IXmlNode; begin // Write something ChildNode := XmlNode.AddChild('Something'); Something.WriteToXmlNode(ChildNode); end; 

And the reading method will look like this:

 procedure TOther.ReadFromXmlNode(XmlNode: IXmlNode) var ChildNode: IXmlNode; begin // Read ChildNode := XmlNode.ChildNodes.First; while Assigned(ChildNode) do begin // Read something if ChildNode.NodeName = 'Something' then Something.ReadFromXmlNode(ChildNode); // Next child node ChildNode := ChildNode.NextSibling; end; end; 

This is a common sense.

I think you will use a similar approach in your example, even if you do not want to serialize XML.

Edit : It was a little incomprehensible what you wanted in your question. If you write components and want the properties of the components to be serialized correctly when you work with them during development, this is not the way to go. The method that I am describing is designed to serialize arbitrary objects at runtime.

+1
source

All Articles