Пусть нам надо уметь сохранять/восстанавливать состояние объекта в поток.
Можно сделать так:
Но лучше так:
А ещё лучше так:
Понятно почему?
Потому что в TReader и TWriter можно убрать "настоящую сериализацию".
Например сделать (грубо) так:
Почему ReadXXX это функция, а не процедура?
А потому, что можно сделать так:
Мысль понятна?
Что-то напоминает?
А что ещё можно сделать?
А можно ВООБЩЕ - НЕ СВЯЗЫВАТЬСЯ с "бинарной сериализацией".
Как?
Позже попробую написать.
А пока почитайте вот что:
http://programmingmindstream.blogspot.ru/2014/04/sax.html
http://programmingmindstream.blogspot.ru/2014/04/blog-post_24.html
http://programmingmindstream.blogspot.ru/2014/04/blog-post_25.html
http://programmingmindstream.blogspot.ru/2014/04/blog-post_104.html
+Igor Belyh Это кстати для вас :-) В продолжение к тому, над чем мы трудимся.
И ещё ссылка - https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html
И ещё:
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdReader.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdWriter.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/K2/k2DocumentBuffer.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/K2/k2DocumentGenerator.pas
Возвращаясь к "бинарной сериализации" - если всё таки "с ней решили связываться".
Понятно, что "следующий шаг" вот такой?
Ну и "вдогонку":
http://programmingmindstream.blogspot.ru/2014/06/blog-post_18.html
http://programmingmindstream.blogspot.ru/2014/06/blog-post_5984.html
Но ПОВТОРЮ, что ОСНОВНАЯ мысль поста в том, что "с бинарной сериализацией" - лучше не связываться.
Лучше оперировать понятием "схемы данных".
И чтение/запись проводить через СХЕМУ, а не "напрямую" из классов.
Ну и ещё:
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdXMLReader.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdCustomXMLReader.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdXMLWriter.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/L3/l3XMLWriter.pas
Почему "не связываться с бинарной сериализацией"?
А потому, что "персистентные хранилища" - они ОЧЕНЬ ПЛОХО к ней относятся. Даже "запись номера версии" - НЕ ПОМОГАЕТ.
У меня когда-то была "бинарная сериализация". В "середине девяностых".
Потом я её заменил на "схему". С поддержкой "бинарной сериализации".
Потом я эту поддержку ГРОХНУЛ. Не так давно. Думая - "ну наверное таких документов уже и в природе не осталось"...
И что вы думаете?
Мне начали "всплывать документы" из "середины 90-х"... И Пользователи начали жаловаться....
Такая вот "долгая память" у "бинарной сериализации"...
Можно сделать так:
type TMyClass = class private f_Integer : Integer; f_Date : TDateTime; f_Cardinal : Cardinal; public procedure SaveTo(aStream: TStream); procedure LoadFrom(aStream: TStream); end;//TMyClass procedure TMyClass.SaveTo(aStream: TStream); begin aStream.Write(f_Integer, SizeOf(f_Integer); aStream.Write(f_Date, SizeOf(f_Date); aStream.Write(f_Cardinal, SizeOf(f_Cardinal); end; procedure TMyClass.LoadFrom(aStream: TStream); begin aStream.Read(f_Integer, SizeOf(f_Integer); aStream.Read(f_Date, SizeOf(f_Date); aStream.Read(f_Cardinal, SizeOf(f_Cardinal); end;
Но лучше так:
type TMyClass = class private f_Integer : Integer; f_Date : TDateTime; f_Cardinal : Cardinal; public procedure SaveTo(aStream: TStream); procedure LoadFrom(aStream: TStream); end;//TMyClass procedure TMyClass.SaveTo(aStream: TStream); begin aStream.WriteBuffer(f_Integer, SizeOf(f_Integer); aStream.WriteBuffer(f_Date, SizeOf(f_Date); aStream.WriteBuffer(f_Cardinal, SizeOf(f_Cardinal); end; procedure TMyClass.LoadFrom(aStream: TStream); begin aStream.ReadBuffer(f_Integer, SizeOf(f_Integer); aStream.ReadBuffer(f_Date, SizeOf(f_Date); aStream.ReadBuffer(f_Cardinal, SizeOf(f_Cardinal); end;
А ещё лучше так:
type TStreamHelper = class private f_Stream : TStream; public constructor Create(aStream: TStream); end;//TStreamHelper TReader = class(TStreamHelper) public function ReadInteger; function ReadDate; function ReadCardinal; end;//TReader TWriter = class(TStreamHelper) public procedure WriteInteger(aValue: Integer); procedure WriteDate(aValue: TDateTime); procedure WriteCardinal(aValue: Cardinal); end;//TWriter TMyClass = class private f_Integer : Integer; f_Date : TDateTime; f_Cardinal : Cardinal; public procedure SaveTo(aStream: TWriter); procedure LoadFrom(aStream: TReader); end;//TMyClass constructor TStreamHelper.Create(aStream: TStream); begin inherited Create; f_Stream := aStream; end; function TReader.ReadInteger; begin f_Stream.ReadBuffer(Result, SizeOf(Result)); end; function TReader.ReadDate; begin f_Stream.ReadBuffer(Result, SizeOf(Result)); end; function TReader.ReadCardinal; begin f_Stream.ReadBuffer(Result, SizeOf(Result)); end; procedure TWriter.WriteInteger(aValue: Integer); begin f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TWriter.WriteDate(aValue: TDateTime); begin f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TWriter.WriteCardinal(aValue: Cardinal); begin f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TMyClass.SaveTo(aStream: TWriter); begin aStream.WriteInteger(f_Integer); aStream.WriteDate(f_Date); aStream.WriteCardinal(f_Cardinal); end; procedure TMyClass.LoadFrom(aStream: TReader); begin f_Integer := aStream.ReadInteger; f_Date := aStream.ReadDate; f_Cardinal := aStream.ReadCardinal; end;
Понятно почему?
Потому что в TReader и TWriter можно убрать "настоящую сериализацию".
Например сделать (грубо) так:
type TStreamHelper = class private f_Stream : TStream; public constructor Create(aStream: TStream); end;//TStreamHelper TSignature = (sigInteger, sigDate, sigCardinal); TReader = class(TStreamHelper) private procedure CheckSignature(aSig: TSignature); public function ReadInteger; function ReadDate; function ReadCardinal; constructor Create(aStream: TStream); end;//TReader TWriter = class(TStreamHelper) private procedure WriteSignature(aSig: TSignature); public procedure WriteInteger(aValue: Integer); procedure WriteDate(aValue: TDateTime); procedure WriteCardinal(aValue: Cardinal); constructor Create(aStream: TStream); end;//TWriter TMyClass = class private f_Integer : Integer; f_Date : TDateTime; f_Cardinal : Cardinal; public procedure SaveTo(aStream: TWriter); procedure LoadFrom(aStream: TReader); end;//TMyClass constructor TStreamHelper.Create(aStream: TStream); begin inherited Create; f_Stream := aStream; end; procedure TReader.CheckSignature(aSig: TSignature); var l_Sig : TSignature; begin f_Stream.ReadBuffer(l_Sig, SizeOf(l_Sig)); Assert(l_Sig = aSig); end; const cVersion = 1; constructor TReader.Create(aStream: TStream); begin inherited; Assert(ReadCardinal = cVersion); end; function TReader.ReadInteger; begin CheckSignature(sigInteger); f_Stream.ReadBuffer(Result, SizeOf(Result)); end; function TReader.ReadDate; begin CheckSignature(sigDate); f_Stream.ReadBuffer(Result, SizeOf(Result)); end; function TReader.ReadCardinal; begin CheckSignature(sigCardinal); f_Stream.ReadBuffer(Result, SizeOf(Result)); end; constructor TWriter.Create(aStream: TStream); begin inherited; WriteCardinal(cVersion); end; procedure TWriter.WriteSignature(aSig: TSignature); begin f_Stream.WriteBuffer(aSig, SizeOf(aSig)); end; procedure TWriter.WriteInteger(aValue: Integer); begin WriteSignature(sigInteger); f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TWriter.WriteDate(aValue: TDateTime); begin WriteSignature(sigDate); f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TWriter.WriteCardinal(aValue: Cardinal); begin WriteSignature(sigCardinal); f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TMyClass.SaveTo(aStream: TWriter); begin aStream.WriteInteger(f_Integer); aStream.WriteDate(f_Date); aStream.WriteCardinal(f_Cardinal); end; procedure TMyClass.LoadFrom(aStream: TReader); begin f_Integer := aStream.ReadInteger; f_Date := aStream.ReadDate; f_Cardinal := aStream.ReadCardinal; end;
Почему ReadXXX это функция, а не процедура?
А потому, что можно сделать так:
type TStreamHelper = class private f_Stream : TStream; public constructor Create(aStream: TStream); end;//TStreamHelper TSignature = (sigInteger, sigDate, sigCardinal); TReader = class(TStreamHelper) private procedure CheckSignature(aSig: TSignature); public function ReadInteger; function ReadDate; function ReadCardinal; end;//TReader TWriter = class(TStreamHelper) private procedure WriteSignature(aSig: TSignature); public procedure WriteInteger(aValue: Integer); procedure WriteDate(aValue: TDateTime); procedure WriteCardinal(aValue: Cardinal); end;//TWriter TMyClass = class private f_Integer : Integer; f_Date : TDateTime; f_Cardinal : Cardinal; public property IntegerProp: Integer read f_Integer write f_Integer; property DateProp: Integer read f_Date write f_Date; property CardinalProp: Integer read f_Cardinal write f_Cardinal; public procedure SaveTo(aStream: TWriter); procedure LoadFrom(aStream: TReader); end;//TMyClass constructor TStreamHelper.Create(aStream: TStream); begin inherited Create; f_Stream := aStream; end; procedure TReader.CheckSignature(aSig: TSignature); var l_Sig : TSignature; begin f_Stream.ReadBuffer(l_Sig, SizeOf(l_Sig)); Assert(l_Sig = aSig); end; function TReader.ReadInteger; begin CheckSignature(sigInteger); f_Stream.ReadBuffer(Result, SizeOf(Result)); end; function TReader.ReadDate; begin CheckSignature(sigDate); f_Stream.ReadBuffer(Result, SizeOf(Result)); end; function TReader.ReadCardinal; begin CheckSignature(sigCardinal); f_Stream.ReadBuffer(Result, SizeOf(Result)); end; procedure TWriter.WriteSignature(aSig: TSignature); begin f_Stream.WriteBuffer(aSig, SizeOf(aSig)); end; procedure TWriter.WriteInteger(aValue: Integer); begin WriteSignature(sigInteger); f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TWriter.WriteDate(aValue: TDateTime); begin WriteSignature(sigDate); f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TWriter.WriteCardinal(aValue: Cardinal); begin WriteSignature(sigCardinal); f_Stream.WriteBuffer(aValue, SizeOf(aValue)); end; procedure TMyClass.SaveTo(aStream: TWriter); begin aStream.WriteInteger(f_Integer); aStream.WriteDate(f_Date); aStream.WriteCardinal(f_Cardinal); end; procedure TMyClass.LoadFrom(aStream: TReader); begin IntegerProp := aStream.ReadInteger; DateProp := aStream.ReadDate; CardinalProp := aStream.ReadCardinal; end;
Мысль понятна?
Что-то напоминает?
А что ещё можно сделать?
А можно ВООБЩЕ - НЕ СВЯЗЫВАТЬСЯ с "бинарной сериализацией".
Как?
Позже попробую написать.
А пока почитайте вот что:
http://programmingmindstream.blogspot.ru/2014/04/sax.html
http://programmingmindstream.blogspot.ru/2014/04/blog-post_24.html
http://programmingmindstream.blogspot.ru/2014/04/blog-post_25.html
http://programmingmindstream.blogspot.ru/2014/04/blog-post_104.html
+Igor Belyh Это кстати для вас :-) В продолжение к тому, над чем мы трудимся.
И ещё ссылка - https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/Reference/Reference.html
И ещё:
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdReader.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdWriter.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/K2/k2DocumentBuffer.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/K2/k2DocumentGenerator.pas
Возвращаясь к "бинарной сериализации" - если всё таки "с ней решили связываться".
Понятно, что "следующий шаг" вот такой?
function TReader.ReadTYPE(const aName: String): TYPE; begin CheckSignature(TYPE); Assert(aName = ReadString); f_Stream.ReadBuffer(Result, SizeOf(Result); end; procedure TWriter.WriteTYPE(const aName: String; aValue: TYPE); begin WriteSignature(TYPE); WriteString(aName); f_Stream.WriteBuffer(aValue, SizeOf(aValue); end;
Ну и "вдогонку":
http://programmingmindstream.blogspot.ru/2014/06/blog-post_18.html
http://programmingmindstream.blogspot.ru/2014/06/blog-post_5984.html
Но ПОВТОРЮ, что ОСНОВНАЯ мысль поста в том, что "с бинарной сериализацией" - лучше не связываться.
Лучше оперировать понятием "схемы данных".
И чтение/запись проводить через СХЕМУ, а не "напрямую" из классов.
Ну и ещё:
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdXMLReader.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdCustomXMLReader.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/EVD/evdXMLWriter.pas
https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/RealWork/L3/l3XMLWriter.pas
Почему "не связываться с бинарной сериализацией"?
А потому, что "персистентные хранилища" - они ОЧЕНЬ ПЛОХО к ней относятся. Даже "запись номера версии" - НЕ ПОМОГАЕТ.
У меня когда-то была "бинарная сериализация". В "середине девяностых".
Потом я её заменил на "схему". С поддержкой "бинарной сериализации".
Потом я эту поддержку ГРОХНУЛ. Не так давно. Думая - "ну наверное таких документов уже и в природе не осталось"...
И что вы думаете?
Мне начали "всплывать документы" из "середины 90-х"... И Пользователи начали жаловаться....
Такая вот "долгая память" у "бинарной сериализации"...
Зачем для сериализации нужна какая-то непонятная "схема данных"?
ОтветитьУдалитьДля решения задачи сохранения состояния объекта эта "схема данных" есть "из коробки" - структура объекта, доступная через RTTI. Ну плюс один-два виртуальных метода для отражения специфики, не укладывающейся в общую схему.
Или Вы не о сериализации, а о маршаллинге говорите?
Тогда понятно: если "на том конце" может быть не Delphi, то какая-то схема, описывающая интерфейс взаимодействия (сигнатуры методов, например, или передаваемые структуры) может пригодится.
Зачем? Этот вопрос надо задать "миллионам людей", которые почему-то "предпочитают бинарную сериализацию". Почему? Вот я тоже хотел бы их спросить. Я на такой код насмотрелся - "выше крыши".
УдалитьПотому и написал этот пост.
Насчёт "из коробки" - конечно МОЖНО. Но тут есть "тонкости".
Во-первых "из коробки" это и есть уже "некая схема данных".
Во-вторых - вы про published или про "новый RTTI"?
Если про Published - Там тоже есть тонкости - например TPersistent.
Если про "новый RTTI", то тем более - потому, что "сериализовать" обычно надо не всё, а лишь что-то. Т.е. это либо "атрибуты" типа [Serealizeable], либо - "мапа". Что тоже является "схемой данных".
«Зачем? Этот вопрос надо задать "миллионам людей", которые почему-то "предпочитают бинарную сериализацию".»
Удалить-- Хорошо, что Вы взяли "миллионы людей" в кавычки :-)
Я из этих "миллионов" знаю только нас (ряд поддерживаемых проектов) да Вас, с Вашим постом про "бинарную сериализацию". IMHO это архаичная техника, которая малополезна в нынешних условиях...
«Во-первых "из коробки" это и есть уже "некая схема данных"»
-- Да, я об этом и сказал. Структура объекта может быть получена средствами RTTI.
«Во-вторых - вы про published или про "новый RTTI"?»
-- Вообще-то я написал просто RTTI. Информация о типах во время выполнения позволяет получить почти всё необходимое для сериализации. В частности, поля отмеченные как published.
«Там тоже есть тонкости - например TPersistent.»
-- Что за тонкости если не секрет? Уж не состоят ли они в том, что от TPersistent нужно наследовать, чтобы обеспечить сериализацию?
Ну так:
«..."сериализовать" обычно надо не всё, а лишь что-то. Т.е. это либо "атрибуты" типа [Serealizeable], либо - "мапа".»
-- Именно так. Не уверен правда, что там нужна какая-то "мапа". Скорее даже - наоборот.
Гораздо проще сериализовать не состояние объекта (класса T), а действительно только то, что требуется.
Для этого "что требуется" легко определить соответствующий класс-потомок TPersistent (класс T', дружественный T). Его published-поля будут хранить то, что мы хотим сериализовать из объекта класса T.
У T' будет конструктор, который будет принимать экземпляр T в качестве параметра (для последующей сериализации экземпляра T'), и метод, выполняющий построение экземпляра T (когда получив экземпляр T' в результате десериализации потребуется получить по нему экземпляр T).
Схема действий при сериализации: для каждого объекта, подлежащего сериализации (T) получить его "образ" (T') и выполнить его сериализацию. При десериализации - выполнить загрузку "образов" (T') и выполнить построение требуемых объектов T.
Роль "схемы данных" играют классы T', предназначенные исключительно для сериализации соответствующих им классов T. Роль "[Serializable]" - published-свойства T', специально предназначенные для сериализации соответствующих им свойств T.
У этой схемы есть один очень существенный плюс.
Поскольку T и T' - разные классы, они создаются независимо, T может измениться очень существенно, но всё равно, чаще всего нетрудно обеспечить корректное построение нового T по старому T'.
Это означает, что мы получаем гораздо большую свободу по рефакторингу T, не сильно оглядываясь на то, что он мог быть сериализован и нужно обеспечивать "совместимость". Поскольку вместо T сериализовался T', изменив реализацию T, мы можем адаптировать реализацию T', чтобы она на основе старых сериализованных данных T' построила новый T после рефакторинга, выставив в умолчательные значения те поля, которые не сериализовались.
Надеюсь, я понятно...
Считайте это "гласом вопиющего"...
УдалитьВы ПРАВИЛЬНО всё пишете... Но почему-то "на практике" - я вижу не совсем то...
Удалить"Вообще-то я написал просто RTTI. Информация о типах во время выполнения позволяет получить почти всё необходимое для сериализации. В частности, поля отмеченные как published."
Удалить"В *частности*, поля отмеченные как published"
-- т.е. всё же про "новый RTTI"... Я понял...
Это по-любому - Delphi XE*
"IMHO это архаичная техника, которая малополезна в нынешних условиях"
Удалить-- именно ТАК, об ЭТО пост собственно и БЫЛ.
"его "образ""
Удалить-- "зеркальный объект", что я и написал...
И отображение объекта в "зеркальный объект" и наоборот - и ЕСТЬ "схема данных".
УдалитьО чём собственно пост.
«"В *частности*, поля отмеченные как published"
Удалить-- т.е. всё же про "новый RTTI"... Я понял...
Это по-любому - Delphi XE*»
-- Да при чём здесь "новый"? Published-свойства объектов, их типы, published-методы объектов можно было "по жизни" в Delphi обрабатывать.
С тех пор, как модуль TypInfo появился.
В том, что я описал ничего кроме этого не нужно.
«"его "образ""
-- "зеркальный объект", что я и написал...»
-- Александр, я не знаю, что такое "зеркальный объект" :-)
Этот термин мне неизвестен, и я не знаю, что он значит для Вас.
То, что используется нами я обозначил.
«И отображение объекта в "зеркальный объект" и наоборот - и ЕСТЬ "схема данных".
О чём собственно пост.»
-- Опять же, Александр... Для меня это никакая не "схема данных", поскольку схема обычно подразумевает структуру данных, обрабатываемую алгоритмами, которым эта структура известна. В данном случае структура конечно есть (RTTI), но она не имеет никакого отношения к соответствию свойств T и T'.
Это соответствие описываются кодом, а не данными. И это - фича, поскольку обеспечивает максимальную гибкость при минимуме усилий. В том смысле наблюдается некая аналогия с Вашей "бинарной сериализацией", но без "порочных наклонностей" вроде последовательности сохранения (от которой, впрочем, легко уйти) и версионности на уровне кода.
T' просто заполняет свои поля из экземпляра T в конструкторе, и создаёт и настраивает экземпляр T по запросу. В сущности, у его те же Load и Store, только переписанные на другом технологическом уровне.
Версионность легко поддерживается многообразием классов T', соответствующих одному T.
Кстати, у нас классы T' называют "фабриками [сериализации]", которые впрочем, имеют отдалённое отношение к паттерну Factory.
Больше мнений хороших и разных :-)
Удалить«"В *частности*, поля отмеченные как published"
Удалить-- т.е. всё же про "новый RTTI"... Я понял...
Это по-любому - Delphi XE*»
-- Да при чём здесь "новый"? Published-свойства объектов, их типы, published-методы объектов можно было "по жизни" в Delphi обрабатывать.
С тех пор, как модуль TypInfo появился.
Про Published и TypInfo - я в курсе.
Но словосочетание "в частности" - вы использовали преднамеренно или по ошибке?
"обрабатываемую алгоритмами, которым эта структура известна"
Удалить-- это как? :-) Расскажете?
@NameRec
Удалить-- вы кстати пробовали создавать/читать dfm'ы размером в десятки/сотни мегабайт?
Налоговый кодекс или Гражданский кодекс - это документы порядка 12-ти мегабайт.
УдалитьСправочник Банковских Идентификационных Кодов - это документ порядка 30-ти мегабайт.
Справочник ОКОФ или ОКОНХ - это документы порядка 30-ти мегабайт.
Я их не пробовал в dfm сериализовать, но подозреваю, что выйдет - больше.
Справочник БИК кстати в RTF - выливается. Но Word его читать отказывается (САМЫЙ современный - не проверял). Тупо - "память кончается". Libre или OpenOffice - читают. Но с некоторой потерей данных.
Интересная кстати задачка - "вылить БИК в dfm-like формат", пусть и бинарный. Не думаю, что я это быстро сделаю. Но когда я это сделаю - я отпишусь о результатах.
УдалитьЭтот комментарий был удален автором.
Удалить«Но словосочетание "в частности" - вы использовали преднамеренно или по ошибке?»
Удалить-- Вопрос не понят.
1. RTTI позволяет не только обрабатывать published свойства.
2. Для большинства задач сериализации от RTTI достаточно published-свойств.
Поэтому, упомянув про RTTI в контексте сериализации я употребил "в частности".
«"обрабатываемую алгоритмами, которым эта структура известна"
-- это как? :-) Расскажете?»
-- Ну например, о схеме данных я счёл бы уместным говорить в случае, если бы T' содержал где-нибудь в своём InitInstance построение словаря вида: {<имя свойства T'>: <имя свойства в T>}. О такой структуре можно было бы говорить как о какой-то "схеме данных", посредством которой можно было бы автоматизировать некоторые действия. Например:
* Убедиться в наличии соответствующих свойств в T и T', а также соответствие их типов.
* Выполнить при инициализации T' по T установку свойств T', а при создании экземпляра T в T' - обратную операцию.
Но в данном случае этот подход мне не представляется уместным.
«@NameRec
-- вы кстати пробовали создавать/читать dfm'ы размером в десятки/сотни мегабайт?»
-- Нет. И я не нахожу удачной идею использования сериализации "из коробки" для таких применений удачной.
Самый большой сериализованный объект, с которым я оказался готов мириться - это отчёт размером 1,5 или 2 MB. Но отчёт действительно был очень большой.
"Десятки-сотни мегабайт DFM" соответствуют десяткам тысяч объектов, попавших в сериализацию, что уже немного странно, принимая во внимание, что число разновидностей этих объектов исчезающе мало в сравнении с количеством этих объектов. В таких случаях обычно (исключения мне неизвестны) предпочтительнее использовать "табличный подход" к сохранению, заключающийся в том, что вначале сериализуется информация о структуре объекта [[<имя свойства 1>, <тип свойства 1>], [<имя свойства 2>, <тип свойства 2>], ...], а сами объекты сохраняются в виде списков значений [<зн. свойства 1>, <зн. свойства 2>], а не словарей вида {<ключ>: <значение>}.
Естественным представлением такой совокупности будет JSON или его бинарные аналоги (BSON, Hessian...).
Вообще же, хотелось бы понять, в каких задачах возникает потребность в таком количестве одновременно существующих объектов, которые и сериализовать нужно к тому же... Это что, граф связей объектов предметной области, с возможностью пользователю вносить изменения в его структуру и расположение элементов?
Мне известна одна такая задача. Но там для сохранения состояния объектов была использована СУБД, кстати HyTech :-)
"RTTI позволяет не только обрабатывать published свойства."
Удалить- каким образом, если мы говорим о "свойствах класса".
"Самый большой сериализованный объект, с которым я оказался готов мириться - это отчёт размером 1,5 или 2 MB. Но отчёт действительно был очень большой."
Удалить-- вот вам и ответ.
"Вообще же, хотелось бы понять, в каких задачах возникает потребность в таком количестве одновременно существующих объектов, которые и сериализовать нужно к тому же..."
Удалить-- я же вам написал - я занимаюсь ОБРАБОТКОЙ документов. БОЛЬШИХ.
"И я не нахожу удачной идею использования сериализации "из коробки" для таких применений удачной."
Удалить-- вот вам и ответ - "зачем схема данных".
"Естественным представлением такой совокупности будет JSON или его бинарные аналоги (BSON, Hessian...)."
Удалить-- JSON - "не очень тянет"... Бинарные аналоги - не пробовал. Ибо уже есть свой.
"В таких случаях обычно (исключения мне неизвестны) предпочтительнее использовать "табличный подход" к сохранению, заключающийся в том, что вначале сериализуется информация о структуре объекта [[, ], [, ], ...], а сами объекты сохраняются в виде списков значений [, ], а не словарей вида {: }."
Удалить-- это "на самом деле" - уже "детали".
"я занимаюсь ОБРАБОТКОЙ документов. БОЛЬШИХ"
Удалить-- примеры документов - я привёл.
Вы кстати знаете сколько страниц занимает Налоговый кодекс в напечатанном виде? А БИК?
УдалитьОтветил в личку :-)
УдалитьЯ прочитал.. Вы - "читаете то что хотите прочитать".. Так "бывает"...
Удалить:-)
УдалитьЯ написал "русски по-белому":
Удалить"Но ПОВТОРЮ, что ОСНОВНАЯ мысль поста в том, что "с бинарной сериализацией" - лучше не связываться."
ДАЛЬШЕ можно обсуждать dfm, xml, json, bjson и т.д. и т.п.
Но это уже - "детали"... ДРУГИЕ "детали"... НЕ СВЯЗАННЫЕ с "бинарной сериализацией"...
Надо ПОНЯТЬ ОДНО - есть "бинарная сериализация" и есть "другая сериализация"...
Про это пост и был..
ТОЛЬКО И ВСЕГО.
Хотите обсуждать "другую сериализацию"?
ДАВАЙТЕ.
НО только - ОТДЕЛЬНО.
Зачем и "что" я сериализую - ТОЖЕ давайте обсуждать ОТДЕЛЬНО.
Поверьте - я 20-ть лет занимаюсь подобными проблемами - и судить о том, что "сноб" я или нет - не вам.. Я ДЕЛЮСЬ СВОИМИ "наработками"...
КРИТИКОВАТЬ - критикуйте...
Но не НАДО только заниматься"нравоучениями"...
Или мы - "беседуем".. Или - НЕТ...
Вы имеете СВОЮ точку зрения, Я - СВОЮ.
У каждого есть "бэкграунд"..
Посему - мы либо "беседуем", либо - НЕТ.
И ещё.. Про RTTI...
УдалитьМы похоже - ОБА знаем про RTTI - "более чем"...
Так что - "не стоит об этом"...
Но слова "В ЧАСТНОСТИ published" - Вы ТАК И НЕ ОБЪЯСНИЛИ..
А если "не в частности"? Что ИМЕННО Вы имели ввиду?
Поясню - в Delphi 7 - RTTTI оперирует ТОЛЬКО published свойствами. В Delphi XE* RTTI оперирует НЕ ТОЛЬКО published свойствами.
Слово "в частности" - написали - ВЫ.
Я вас к этому - НЕ ВЫНУЖДАЛ.
Либо - "признайте СВОЮ ошибку", либо "мы говорим о XE*".
Тот и другой варианты - они - ПЕРСПЕКТИВНЫ...
И ещё...
УдалитьПОЙМИТЕ ОДНУ простую вещь..
Я ведь пишу не для ВАС...
Вы и БЕЗ МЕНЯ - ПРЕКРАСНО всё понимаете.
Я пишу для тех "миллионов", которые применяют "бинарную сериализацию" и другие "архаичные техники".
Вы ведь МЕСТАМИ - "на голову выше" меня... Хотите "укусить" - кусайте.. Но зачем? Я ведь пишу не "для Вас", а для "миллионов", которые не "пережили архаичные техники"...
УдалитьЯ за последние несколько месяцев увидел "не одного" сторонника "бинарной сериализации".... Вот и "считайте"..
УдалитьИ ещё...
УдалитьЯ 20-ть "с копейками" лет занимаюсь "обработкой документов"... Если МОЙ опыт - неинтересен - Ок, не буду писать о нём... Если же ИНТЕРЕСЕН, то не стоит "считать меня снобом"...
Но! Если "опыт неинтересен" то ПИШИТЕ ПРО "свой опыт".. а не КРИТИКУЙТЕ меня.... Вы - ПИШИТЕ про "свой" опыт" - Я - про "свой"...
УдалитьНе КРИТИКОВАТЬ.. а ПИСАТЬ... Ок?
Я одного не понял...
УдалитьГде (процитируйте) Вы увидели критику того, что у Вас?
Я не знаю как у Вас (Вашего кода я не видел) - у меня просто нет предмета критики :-)
Вы задавали вопросы, я на них отвечал.
По поводу "в частности" тоже ответил.
То, что было непонятно мне самому (зачем сейчас использовать именно "бинарную" и именно сериализацию) - спросил.
Поясню - в Delphi 7 - RTTTI оперирует ТОЛЬКО published свойствами.
RTTI как Вам известно, предоставляет информацию о типах во время выполнения, и использование этой информации не сводится только к работе с published-свойствами.
Далее, контекст, в котором я использовал словосочетание "в частности", вызвавшее у Вас столько вопросов, был следующий:
««Во-вторых - вы про published или про "новый RTTI"?»
-- Вообще-то я написал просто RTTI. Информация о типах во время выполнения позволяет получить почти всё необходимое для сериализации. В частности, поля отмеченные как published.»
В System.Classes.TObject есть методы для определения адресов методов и полей объектов по имени, в TypInfo - функции преобразования enum-значений. Не уверен, что всё перечислил. Но всё это может быть использовано совершенно независимо от published-свойств, и за рамками сериализации. Ну и при сериализации/десериализации, разумеется, тоже может. Другой вопрос, как и зачем.
«Либо - "признайте СВОЮ ошибку", либо "мы говорим о XE*".»
-- Перед тем, как признавать ошибку, неплохо сначала понять, в чём она состоит ;-)
«Я за последние несколько месяцев увидел "не одного" сторонника "бинарной сериализации".... Вот и "считайте"..»
-- Мне было бы интересно узнать, какие соображения делают их сторонниками именно сериализации и именно "бинарной" её разновидности.
«Но! Если "опыт неинтересен" то ПИШИТЕ ПРО "свой опыт"..»
-- Да почему сразу "не интересен"... Непонятен — да, но если бы был неинтересен, стал бы я писать?
То, что используется у нас - постарался подробно описать, когда говорил о сериализации "фабрик объектов".
Альтернативный сериализации вариант с сохранением раздельно метаданных и данных - тоже.
Сериализация ведь очень специфическая вещь. В силу необходимости восстановления ссылок между десериализуемыми объектами, приходится держать эти объекты в оперативной памяти. IMHO если объектов много, разумно озаботиться альтернативными сериализации механизмами обеспечения персистентности.
Главным образом, поскольку (цитата из Википедии):
«Любой из схем сериализации присуще то, что кодирование данных последовательно по определению, и извлечение любой части сериализованной структуры данных требует, чтобы весь объект был считан от начала до конца и воссоздан. Во многих приложениях такая линейность полезна, потому что позволяет использовать простые интерфейсы ввода-вывода общего назначения для сохранения и передачи состояния объекта. В приложениях, где важна высокая производительность, может иметь смысл использовать более сложную, нелинейную организацию хранения данных.»
Говорю очевидные вещи? - не Вам, Александр, а "миллионам" о которых Вы упомянули.
Никакой иронии. Честное слово.