Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Десериализация сложных объектов в OmniXML: работа со списками объектов

Delphi , Интернет и Сети , XML

OmniXML является популярным компонентом для сериализации и десериализации объектов в Delphi, который позволяет сохранять состояние объектов в XML и восстанавливать его. Однако, при работе со сложными структурами, такими как списки объектов, могут возникать вопросы о том, как правильно организовать процесс сериализации и десериализации.

Проблема

Для начала рассмотрим пример класса TConfiguration, который содержит свойство TheList типа TList<TMyObject>. TMyObject является прямым потомком TPersistent, что делает его потенциально сериализуемым через OmniXML. Однако, TList сам по себе не является потомком TPersistent, и здесь возникает вопрос: может ли OmniXML десериализовать объект, содержащий список объектов?

unit u_Configuration;

interface

uses
  Classes,
  Generics.Collections,
  OmniXML,
  OmniXMLPersistent;

type
  TMyObject = class(TPersistent)
  strict private
    fName : String;
  published
    property Name: String read fName write fName;
  end;

  TConfiguration = class(TPersistent)
  strict private
    fTheList : TList<TMyObject>;
  published
    property TheList: TList<TMyObject> read fTheList write fTheList;
  end;

implementation
// ...
end.

Альтернативный ответ

Структура класса TConfiguration остается неизменной, но вопрос заключается в том, как правильно организовать процесс сериализации объекта с таким списком.

Подтвержденный ответ

OmniXML действительно поддерживает сериализацию объектов, являющихся потомками TPersistent, включая их свойства. Однако, для свойств, имеющих объекты в качестве типов, OmniXML будет сериализовать только те объекты, которые также являются потомками TPersistent. TList является потомком TEnumerable, который, в свою очередь, является потомком TObject, и не удовлетворяет условиям для сериализации OmniXML. Тем не менее, OmniXML имеет встроенную специальную обработку для TCollection и его потомков, что позволяет сериализовать списки объектов.

Решение

Чтобы сериализовать объекты с свойствами, содержащими списки объектов, необходимо убедиться, что сам список и все объекты в нем являются потомками TPersistent. Например, для TList<TMyObject> это условие выполняется, и OmniXML сможет корректно обработать сериализацию.

Пример кода

unit u_Configuration;

interface

uses
  Classes,
  Generics.Collections,
  OmniXML,
  OmniXMLPersistent;

type
  TMyObject = class(TPersistent)
  strict private
    fName : String;
  public
    constructor Create(const AName: String);
    published
    property Name: String read fName write fName;
  end;

  TConfiguration = class(TPersistent)
  strict private
    fTheList : TList<TMyObject>;
  public
    constructor Create;
    procedure SaveToXML(const FileName: TFileName);
    procedure LoadFromXML(const FileName: TFileName);
  published
    property TheList: TList<TMyObject> read fTheList write fTheList;
  end;

implementation

// Конструктор для TMyObject
constructor TMyObject.Create(const AName: String);
begin
  inherited Create;
  Name := AName;
end;

// Методы для сохранения и загрузки TConfiguration
constructor TConfiguration.Create;
begin
  inherited Create;
  fTheList := TList<TMyObject>.Create;
end;

procedure TConfiguration.SaveToXML(const FileName: TFileName);
var
  XMLWriter: TXMLWriter;
begin
  XMLWriter := TXMLWriter.Create(nil);
  try
    XMLWriter.RootElement := 'Configuration';
    XMLWriter.AutoCommit := False;
    XMLWriter.Indented := True;
    XMLWriter.WriteNode(fTheList);
    XMLWriter.Commit;
    XMLWriter.SaveToFile(FileName);
  finally
    XMLWriter.Free;
  end;
end;

procedure TConfiguration.LoadFromXML(const FileName: TFileName);
var
  XMLReader: TXMLReader;
begin
  XMLReader := TXMLReader.Create(nil);
  try
    XMLReader.DocumentURI := FileName;
    fTheList.Clear;
    while not XMLReader.EndOfFile do
    begin
      if XMLReader.IsStartNode then
        with TMyObject.Create(XMLReader.GetAttributeValue('Name')) do
        begin
          try
            Assign(XMLReader);
            fTheList.Add(Self);
          finally
            Free;
          end;
        end;
      XMLReader.ReadNode;
    end;
  finally
    XMLReader.Free;
  end;
end;

// Инициализация обработчика для TList<TMyObject>
procedure RegisterCustomHandler;
begin
  RegisterClassHandler(TList<TMyObject>.classinfo, TListHandler<TMyObject>.Create(nil));
end;

initialization
  RegisterCustomHandler;
end.

В этом примере мы создаем конструкторы для классов TMyObject и TConfiguration, а также методы для сохранения и загрузки объекта TConfiguration в XML. Важно также зарегистрировать специальный обработчик для TList<TMyObject>, чтобы OmniXML мог корректно работать со списками.

Заключение

OmniXML предоставляет мощные возможности для сериализации объектов в Delphi, но требует правильного понимания его ограничений и особенностей работы с коллекциями. Следуя приведенным рекомендациям, можно успешно сериализовать и десериализовать сложные объекты, содержащие списки других объектов.

Создано по материалам из источника по ссылке.

OmniXML позволяет сериализовать объекты, содержащие списки других объектов, при условии, что эти объекты являются потомками `TPersistent`.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: XML ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 12:57:10/0.0036511421203613/0