Cериализация для начинающих - Часть 3 - Сериализация однородной коллекции

ОГЛАВЛЕНИЕ

Сериализация однородной коллекции

Однородные коллекции используются для хранения коллекций с динамически изменяемым размером, содержащих объекты одинакового типа. Для сериализации однородной коллекции нужно сделать следующее:

  1. Сериализовать сигнатуру и версию объекта
  2. Сериализовать базовый класс объекта (если он есть)
  3. Сериализовать число элементов в коллекции << дополнительный шаг
  4. Сериализовать каждый объект в коллекции << дополнительный шаг
  5. Сериализовать элементы (члены) объекта (если они есть)

В следующем примере класс ColoredPointList является коллекцией объектов ColoredPoint. Для простоты ColoredPointList использует CPtrArray для хранения объектов. Как и все упорядочиваемые классы, ColoredPointList также определяет статическую сигнатуру и версию. Здесь представлено как ColoredPointList: выглядит

   class ColoredPointList

  {
    // Конструктор/Деструктор
    public:
      ColoredPointList::ColoredPointList();
      virtual ColoredPointList::~ColoredPointList() 

    // Атрибуты
    public:
      static const CString m_strSignature;
      static const int m_nVersion;

    // Операции
    public:
      int serialize (CArchive* pArchive);
    // Члены
    protected:
      CPtrArray m_coloredPoints;  }

Здесь показана его сериализация:

   int ColoredPointList::serialize

    (CArchive* pArchive)
  {
    ASSERT (pArchive != NULL);
    int nStatus = Status::Success;
 
    // Шаг 1: Сериализация сигнатуры и версии
    int nVersion;
    try {
      if (pArchive->IsStoring()) {
          (*pArchive) << ColoredPointList::m_strSignature;
          (*pArchive) << ColoredPointList::m_nVersion;

      } else {
          CString strSignature;
          (*pArchive) >> strSignature;
          if (strSignature != ColoredPointList::m_strSignature)
             return (Status::InvalidFormat);
          (*pArchive) >> nVersion;
          if (nVersion > ColoredPointList::m_nVersion;)
             return (Status::UnsupportedVersion);
      }

      // Шаг 2: Сериализация базового класса (если он есть)
      //
      // Ничего не выполняется, так как ColoredPointList не является производным классом.
      // Но если бы он был произведен от BaseColoredPointList, то выполнялся бы ряд действий:
      //
      // nStatus = BaseColoredPointList::serialize (pArchive);
      // if (nStatus != Status::Success)
      //    return (nStatus);

      // Шаг 3: Сериализация числа элементов в коллекции
      int nItems = 0;
      if (pArchive->IsStoring()) {
           nItems = m_coloredPoints.GetSize();
           (*pArchive) << nItems;

      } else
         (*pArchive) >> nItems;

      // Шаг 4: Сериализация каждого объекта в коллекции
      for (int nObject=0; (nObject < nItems); nObject++) {

          // 4a: Сериализация указателя на объект

          ColoredPoint* pColoredPoint = NULL;
          if (pArchive->IsStoring())
             pColoredPoint = (ColoredPoint *) m_coloredPoints.GetAt (nObject);
          else
             pColoredPoint = new ColoredPoint();

          ASSERT (pColoredPoint != NULL);
 
          // 4b: Сериализация объекта
          nStatus = pColoredPoint->serialize (pArchive);

          if (nStatus != Status::Success)
             return (nStatus);
          if (!pArchive->IsStoring())
             m_coloredPoints.Add (pColoredPoint);

      }
 
      // Шаг 5: Сериализация других элементов объекта (если они есть)
      //
      // Ничего не делается, так как ColoredPointList не имеет никаких других элементов. Но если бы он содержал целочисленный элемент (m_nSomeInt) и объект Foo
      //  (m_foo), выполнялись бы следующие действия:
      //
      // if (pArchive->IsStoring())
      //    (*pArchive) << m_nSomeInt;
      // else
      //    (*pArchive) >> m_nColor;
      //
      // nStatus = m_foo::serialize (pArchive);
      // if (nStatus != Status::Success)
      //    return (nStatus);
    }

    catch (CException* pException) {
      // Произошла ошибка чтения/записи
      pException->Delete();
      if (pArchive->IsStoring())
        return (Status::WriteError);
      return (Status::ReadError);
    }

    // Объект был успешно сериализован (упорядочен)
    return (Status::Success);

  }