It only works if you put your collection in a TComponent, because TMemoryStream.WriteComponent (the name itself is a clue!) takes a TComponent as a parameter:
procedure WriteComponent(Instance: TComponent);
and TCollection is as you already discovered not a TComponent descendant. It may seem odd to have a TComponent descendant just to hold your TCollection descendant, but if you want to stream it using the WriteComponent facilities of streams, I don't see any other easy way to do it.
If you want to do this using "just" the RTL/VCL (ie not using a third party library), you would have to write a T(Memory)Stream descendant and add a WritePersistent implementation that takes an Instance: TPersistent
parameter.
I haven't delpheddelved into the TStream classes that much, but my guess is that you w/should be able to borrow a lot from the TComponent support. Certainly the class inheritance support.
Having had a cursory look, it seems simple at first as WriteComponent
just calls WriteDescendent
which instantiates a TWriter
and then calls the WriteDescendent
method of that writer. And the TWriter already contains methods to write a collection.
However, if you "just" want to stream TPersistent descendants, you will have to do a lot of work in TWriter/TReader as well as they are completely based around TComponent. And it won't be a simple case of just writing a couple of descendant. For one, they TWriter/TReader are not really set up to be derived from. For another: TStream (descendants) instantiate TWriter and TReader directly and these classes do not have virtual constructors. Which makes writing descendants for them fairly futile unless you would like to try your hand at hooking, patching the VMT and more of that interesting stuff.
All in all: the easiest way to stream your custom collection remains to "just" wrap it in a TComponent and live with the "waste" of that.