А задачка-то, оказывается, имеет точное решение.
Репликация - это та же самая сериализация, но только растянутая во времени и пространстве и ещё с возможностью пере-экстернализировать уже экстернализированный ранее объект. То есть мы берём и экстернализируем объект за объектом, экстернализируем, экстернализируем, а потом вдруг говорим - стоп, а вот этот вот объектик пере-экстернализируйте пожалуйста ещё разочек, и продолжаем этот процесс сколь угодно долго. В результате постоянно имеем копию произвольного графа объектов изменяющуюся синхронно с оригиналом.
По сравнению со Stores.Store у реплицируемого объекта есть ещё парочка методов: ReExternalize и ReInternalize. Они предназначены специально для (повторной) модификации ранее экстернализированного/интернализированного объекта. Через них может передаваться не всё состояние объекта, а лишь его модификация, что может быть существенно меньше по объёму.
Есть сервис репликации, у которого есть метод Service.Commit(obj: Object) экстернализирующий или пере-экстернализирующий указанный объект. Когда у объекта-оригинала изменяется состояние, то он сообщает об этом сервису репликации вызывая: service.Commit(this). Если (пере)экстернализируемый объект ссылается на другие объекты и они ещё не были ни разу экстернализированы, то они экстернализируются. Пере-экстернализация выполняется только по явной команде.
У каждого реплицируемого объекта есть скрытое поле - GUID, благодаря ему восстанавливаются все взаимные ссылки при десериализации.
В процессе работы программы объект-оригинал может быть удалён. В своём финализаторе он извещает об этом все репликационные сервисы, в которых он за время своей жизни успел зарегистрироваться (а внутри этих сервисов, разумеется, хранятся лишь "слабые ссылки" на объекты). Сервис, получив извещение о смерти объекта-оригинала рассылает специальные сообщения всем клиентам, и те освобождают соответствующие объекты-копии.
Концептуальный интерфейс:
Код:
DEFINITION Replication;
TYPE
Object = POINTER TO ABSTRACT RECORD
(obj: Object) Externalize- (VAR wr: Writer), NEW, EXTENSIBLE;
(obj: Object) Internalize- (VAR rd: Reader), NEW, EXTENSIBLE;
(obj: Object) ReExternalize- (VAR wr: Writer), NEW, EXTENSIBLE;
(obj: Object) ReInternalize- (VAR rd: Reader), NEW, EXTENSIBLE
END;
Reader = LIMITED RECORD
(VAR rd: Reader) ReadByte (OUT b: BYTE), NEW;
(VAR rd: Reader) ReadBytes (OUT buffer: ARRAY OF BYTE; offset, count: INTEGER), NEW;
...
(VAR rd: Reader) ReadObject (OUT obj: Object), NEW
END;
Writer = LIMITED RECORD
(VAR wr: Writer) WriteByte (b: BYTE), NEW;
(VAR wr: Writer) WriteBytes (IN buffer: ARRAY OF BYTE; offset, count: INTEGER), NEW;
...
(VAR wr: Writer) WriteObject (obj: Object), NEW
END;
Service = POINTER TO ABSTRACT RECORD
(c: Channel) Commit (obj: Object), NEW, ABSTRACT;
END;
PROCEDURE NewService (listenerEndPoint: ARRAY OF CHAR): Service;
END Replication.