You state that serialization is not a solution but I ask why not?  I've done something like this in the past but here is what I've done.
I created a component class that did nothing but serialize a non-TPersistant based object so that I could stream it in and out using VCL streaming capabilities.
For example:
//Please forgive me for any errors that exist, as I'm trying to type this from the top of my head. As well, this is not going to be functionally complete. 
unit streamlist1;
interface
uses MyListObjectUnit;
procedure SaveList(fielname:string; data:TMyListObject);
procedure LoadList(filename:string; var data:TMyListObject);
implementation
type
  TMyListStreamer = class(TComponent)
  private
    fMyList : TMyListObject;
    procedure ReadList(Reader:TReader); //This is where the magic happens
    procedure WriteList(Writer: TWriter); //This is where the magic happens (x2)
  public
    procedure DefineProperties(Filer: TFiler); override; //defined in TPersistent
    procedure AssignMyList(data:TMyListObject);
    procedure PopulateData(var data:TMyListObject);
  end;
TMyListStreamer.procedure DefineProperties(Filer: TFiler); override; //defined in TPersistent
begin
  Filer.DefineProperty('MyObjList', ReadList, WriteList, true);
  //Filer.DefineBinaryProperty('MyObjList', ReadList, WriteList, true); //your choice
end;
procedure TMyListStreamer.ReadList(Reader:TReader); //This is where the magic happens
begin
  //Use the reader class to read in anything you want...
end;
procedure TMyListStreamer.WriteList(Writer: TWriter); //This is where the magic happens (x2)
begin
  //Use the writer class to write out anything you want...
end;
procedure SaveList(fielname:string; data:TMyListObject);
var
  wFile : TFileStream;
  wList : TMyListStreamer;
begin
  RegisterClass(TMyListStreamer);
  Try
    wFile := TFileStream.Create(filename, fmcreate);
    wList := TMyListStreamer.create(nil);
    try
      wList.AssignMyList(Data);
      wFile.WriteComponent(wList);
    finally
      wFile.Free;
      wList.free;
    end;
  finally
    Unregisterclass(TMyListStreamer);
  end;
end;
procedure LoadList(filename:string; var data:TMyListObject);
var
  wFile : TFileStream;
  wList : TMyListStreamer;
begin
  RegisterClass(TMyListStreamer);
  Try
    wFile := TFileStream.Create(filename, fmOpenRead);
    try
      wList := TMyListStreamer(wFile.ReadComponent(Nil));
      if assigned(data) and assigned(wList) then
        wList.PopulateData(data);
      if assigned(wList) then
        wList.free; 
    finally
      wFile.Free;
    end;
  finally
    Unregisterclass(TMyListStreamer);
  end;
end;
Using this method you can stream (serialize) anything out of the VCL or custom data.
It takes a little to set up, but the strength is that you can control everything going in and out of the data file.  You can even, with a little fore thought, create a version flag and process different data by ignoring or massaging specific data in newer versions of the program/component.
You can even stream other VCL objects out of your streaming component as long as you already know the type of object (ie TComponent/TPersistant based objects)  by using the existing methods of the TReader/TWriter.
Not a full solution but it should get you where you want to go with a little more work.