Дата публикации статьи: 17.10.2004 16:31

Velin
Концепция разработки приложений DTM

  • Что такое DTM?
  • Описание XMLExt
  • Как работать со статьей
  • Типы данных
  • Простейшие операции с данными
  • Место хранения
  • Идентификация типа файла
  • Структура файла
  • Self-file функции
  • Пример класса
  • Функции, упрощающие жизнь
  • XML объекты
  • Пример класса
  • XML коллекции
  • Пример класса
  • Модель данных
  • IFileOutput
  • Пример класса
  • Скачать архив к статье
  • Обсудить в форуме
  • Что такое DTM?

        DTM - это технология создания структуры программного продукта. Пока DTM включает в себя только одну ступень - DTM1, или простейшая модель иерархических данных.

    Описание XMLExt

        Пакет DANAsoft XML COM Extension представлен ActiveX библиотекой DANAXMLExt.dll. Между тем сразу замечу, что от одной лишь этой библиотеки толку Вам будет мало. На мой взгляд, Вам гораздо полезнее будет прочитать эту статью. А библиотека используется для стандартизации, и не более. В DANAsoft XML COM Extension также входит набор шаблонов.

    Загрузить:

  • Бибилиотека XMLExt (установочный файл) - setup.exe*
  • Набор шаблонов (в формате txt) - templts.zip*
    Как работать с этой статьей

        Для начала, Вы должны понять, сможете ли Вы использовать преимущества DTM. Для этого мы предлагаем Вам скачать с нашего сайта пример реализации DTM.

  • Телефонная книга - tel_book.zip*
        Как работать с этими примером? Разбирать пример начинайте с клиентского проекта (не забыв зарегистрировать DLL). Ведь основная мысль DTM в том, что бы максимально упростить создание клиентских приложений. Определив, как работает клиентское приложение, вы можете перейти к DLL. Ее работа будет подробно рассмотрена в этой статье.

    Типы данных

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

    Простейшие типы данных
    Сокращение Описание Эквивалент на VB\C++
    lng Целое число Long\long
    str Строка String\BSTR
    bool Логическое значение(да\нет) Boolean\bool
    dbl Дробное число Double\double
    bin Блок двоичных данных Byte()\BYTE[]
    sbj Особые данные, преобразуемые в одну строку XML_SingleNode_object
    obj Блок данных XMLObject
    Собственно все. Хотя назовите хоть одну область, где нельзя было бы ограничиться этими типами!
    Простейшие операции с данными

        В нашем понимании данные можно хранить(т.е. считывать и записывать), создавать, обрабатывать, и многое другое. Из всего этого в нашей статье мы поговорим о трех простейших операциях.

    1. Запись(сохранение)

    2. Считывание(загрузка)

    3. Создание

        Данные в нашем понимании хранятся в секциях - нодах, соответственно функции будут называться SaveNode_xxx, LoadNode_xxx, CreateNode_xxx.
    xxx - это соответственно тип данных(к прим. для сохранение булевого значения используется функция SaveNode_bool()).
        Стоит отметить, что из всех имеющихся Create-функций на практике используется, пожалуй, только CreateNode_obj. Другие используются крайне редко(о причинах расскажем позже).

    Место хранения

        Мы кажется забыли, про одну очень важную операцию с данными - хранение. Впрочем это лишь потому, что нас это и не интересует. Мы лишь записываем данные, а аппаратно-программные средства компьютера следят, что бы к моменту считывания данных они не изменились.
        Впрочем, сделаем маленькое отвлечение от абстрактной модели, и задумаемся над тем, что данные надо-таки где-то хранить. При работающем компьютере они будут храниться в виртуальной памяти. Ну а по выключении - на винчестере(или ином носителе).
        Переходя к компьютерной модели можно сказать, что данные будут храниться в файлах. В связи с чем, позвольте представить Вам интерфейс IFileInputOutput.

        Классы реализующие интерфейс IFileInputOutput отвечают за запись/считывание данных в какой-то отдельный файл на диске. Обычно каждый класс обрабатывает файлы с каким-то конкретным расширением.

    Файлы, в которых хранятся данные не простые. Есть ряд особенностей.
    1. Данные хранятся в формате XML 1.0

    2. Кодировка фалов - UNICODE
    3. Расширение фалов - из шести букв(к прим. .XMEDAT)(рекомендуеться)
    4. Ограничение для стандарта XML: Ноды не должны иметь смешанные типы(т.е. вариант типа <node>Text data<sub-node>subnode-data</sub-node></node> недопустим). В ноде размещается либо текст, либо другие ноды.
    5. В начале файла есть два специальных тега: file-content-type и file-content-version. Пояснения будут ниже.

    Интерфейс IFileInputOutput имеет следующие свойства и методы:

  • ReadFile(FileName)
  • WriteFile(FileName)
  • CreateFile
  • CloseFile
  • FileName - Property get
  • FileContentType - Property get
  • SetFileContentType(NewVal)
        Назначение первых четырех, я думаю очевидно. FileName - это строка, содержащая имя последнего файла, который был прочитан или записан. FileContentType - свойство возвращает структуру FileContentType. Эта структура содержит следующие переменные-члены:

  • ContentType
  • ContentVersion
    Данная структура указывает тип загруженного в объект файла.
    SetFileContentType - этот метод используется self-file-функциями(подробнее ниже), устанавливает тип загруженного в объект файла.

    Идентификация типа файла

        Идентификация типа файла производиться по трем признакам: расширению файла, его content-type и имени корневого элемента. Идентификация типа нужна, что бы уменьшить количество ошибок. Так если к примеру, класс для обработки файлов с одним содержимым начнет обрабатывать фалы с другим содержимым, это повлечет за собой целый ряд ошибок. Поэтому, каждый раз перед началом загрузки фала(ReadFile) класс должен убедиться, что это именно тот тип, который он может обработать. В данном случае опираться на расширение файла не рекомендуется. Мы советуем вам проверять только два последних признака(content-type и имени корневого элемента).
        Надеюсь, что нижеследующее описание пояснит вышесказанное.

    Структура файла

    <ROOT_ELEMENT>
       <file-content-type>Simple type</file-content-type>
       <file-content-version>1.0</file-content-version>
       ...elements...
    </ROOT_ELEMENT>
       
    Вот так выглядит любой файл данных по стандарту XMLExt. Здесь SimpleType это тип содержимого, 1.0 - версия типа содержимого. ROOT_ELEMENT - это корневой элемент. По стандарту XMLExt у вашего файла может быть любое название для элемента верхнего уровня(так, если файл хранит информацию о записке, то это будет Note, если это телефонная книга - TelefonList). Если воображения не хватает - используйте root. Значение file-content-type может быть любая строка. Хотя желательно придерживаться следующей нотации: Название_компании Название_программы Название_формата Например: DANAsoft ProgMan SourceManList.

    Self-file-функции
    Их три:
  • self_ReadFile(f_io As IFileInputOutput, aXML As MSXML2.DOMDocument, root_name As String, file_name As String, rt_node As MSXML2.IXMLDOMNode)

  • self_CreateFile(f_cont As FileContentType, aXML As MSXML2.DOMDocument, root_name As String, rt_node As MSXML2.IXMLDOMNode)

  • self_WriteFile(aXML As MSXML2.DOMDocument, file_name As String, [aErrNum As Long = 0])
        Первая функция возвращает значения из перечисления(enum) self_ReadFile_Return. Остальные две функции возвращают значение типа Byte(1 - ошибок не было, 0 - произошла ошибка). Особенность всех self-функций в том, что их вызов гарантировано не взывает ошибок. В случае, если выполнить функцию невозможно, она просто оповещает Вас об этом через возвращаемое значение.
    Параметры self_ReadFile:

    1. f_io - ссылка на ваш объект(для вызова SetFileContentType)
    2. aXML - ссылка на объект DOMDocument, в который будет загружен XML-файл

    3. root_name - Имя корневого элемента
    4. file_name - Имя считываемого файла
    5. rt_node - В эту переменную функция поместит указатель на корневой элемент.
    Параметры self_CreateFile:
    1. f_cont - ссылка на создаваемый FileContentType
    2. aXML - ссылка на объект DOMDocument, в котором будет создан XML-файл
    3. root_name - Имя корневого элемента
    4. rt_node - В эту переменную функция поместит указатель на корневой элемент.
    Параметры self_WriteFile:
    1. aXML - ссылка на объект DOMDocument, который будет записан в XML-файл
    2. file_name - Имя записываемого файла
    3. aErrNum - В случае ошибки в эту переменную будет помещена Err.Number. Параметр необязательный

        Функция self_ReadFile вызывает функцию SetFileContentType Вашего объекта, и передает ей параметры, прочитанные из XML-документа. Ваша функция сверяет, действительно ли объект может прочитать файл с таким типом и возвращает 1 если мажет, и 0 если не может.

    Пример класса, реализующего IFileInputOutput

        Для того, что бы получше понять интерфейс IFileInputOutput мы предлагаем Вам написать класс TelefonBookFile, хранящий данные телефонной книги в файлах с расширением XMETBK, и реализующий IFileInputOutput:

    Implements IFileInputOutput 'Указываем VB, что файл реализует интерфейс IFileInputOutput
    Dim mXML As MSXML2.DOMDocument 'Переменная хранящая XML-документ
    Dim mfName As String 'Имя файла
    Dim mfc As FileContentType 'Тип файла
    Dim mRootNode As MSXML2.IXMLDOMNode 'Корневой элемент
    Private Const FILE_CTYPE = "DANA Diary Data file" 'Константа, содержит название типа файла
    Private Const FILE_ROOTNODE = "TELBOOK" 'Константа, содержит имя корневого элемента
    'CLASS_SUBITEMS{{
    'ПОМЕСТИТЕ ЗДЕСЬ операторы объявления всех элементов класса
    '}}CLASS_SUBITEMS
    
    '==================================
    '=======This class DTMItems========
    '==================================
    'CLASS_SUBITEMS_PROPS{{
    'ПОМЕСТИТЕ ЗДЕСЬ операторы Propertu Let/Get для всех элементов класса
    '}}'CLASS_SUBITEMS_PROPS
    
    'Эти строки указывают, что дальше следует реализация IFileInputOutput
    '==================================
    '==IFileInputOutput implementation=
    '==================================
    Private Sub IFileInputOutput_CloseFile()
    'CLASS_SUBITEMS_CLOSE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для уничтожения всех элементов класса
    '}}CLASS_SUBITEMS_CLOSE
    Set mRootNode = Nothing
    Set mXML = Nothing
    mfName = ""
    End Sub
    
    Private Sub IFileInputOutput_CreateFile()
    Set mXML = New MSXML2.DOMDocument
    mfc.ContentType = FILE_CTYPE
    mfc.ContentVersion = "1.0"
    Call self_CreateFile(mfc, mXML, FILE_ROOTNODE, mRootNode)
    'CLASS_SUBITEMS_CREATE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для инициализации и создания всех элементов класса
    '}}CLASS_SUBITEMS_CREATE
    mfName = ""
    End Sub
    
    Private Property Get IFileInputOutput_FileContentType() As DANAProgManXMLExt.FileContentType
    IFileInputOutput_FileContentType = mfc
    End Property
    
    Private Property Get IFileInputOutput_FileName() As String
    IFileInputOutput_FileName = mfName
    End Property
    
    Private Sub IFileInputOutput_ReadFile(ByVal afName As String)
    Set mXML = New MSXML2.DOMDocument
    If self_ReadFile(Me, mXML, FILE_ROOTNODE, afName, mRootNode) <> srfOK Then
    IFileInputOutput_CloseFile
    Exit Sub
    End If
    'CLASS_SUBITEMS_LOAD{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для инициализации и загрузки всех элементов класса
    '}}CLASS_SUBITEMS_LOAD
    mfName = afName
    End Sub
    
    Private Function IFileInputOutput_SetFileContentType(NewVal As _
    DANAProgManXMLExt.FileContentType) As Byte
    If NewVal.ContentType = FILE_CTYPE And NewVal.ContentVersion = "1.0" Then
    mfc = NewVal
    IFileInputOutput_SetFileContentType = 1
    Else
    IFileInputOutput_SetFileContentType = 0
    End If
    End Function
    
    Private Sub IFileInputOutput_WriteFile(ByVal afName As String)
    'CLASS_SUBITEMS_SAVE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для сохранения всех элементов класса
    '}}CLASS_SUBITEMS_SAVE
    self_WriteFile mXML, afName
    mfName = afName
    End Sub
    

        Вот такая вот реализация. Считайте, что это шаблон для всех ваших будущих классов, реализующих IFileInputOutput. Обратите внимание, что при создании класса следует обращать внимание только на изменение констант и добавление строк в "'ПОМЕСТИТЕ ЗДЕСЬ" (об этом позже). На остальное можете смело не обращать внимание. Особо обращаю Ваше внимание, что данный код не отлавливает, что возвращают self_функции. Для первичного понимания это не требуется.

    Функции, упрощающие жизнь

        Их название начинается с fio_. Их имена я приводить здесь не буду, если интересно посмотрите в object browser'е.(F2 в среде Visual Basic). Эти функции вызывают соответствующую функцию-член переданного ей объекта. Например, вот код функции fio_ReadFile: Sub fio_ReadFile(ByRef obj As IFileInputOutput, ByVal fName As String)
    obj.ReadFile fName
    End Sub

    Вот собственно и вся функция. Вам, возможно станет интересно, для чего она нужна? Это вы поймете, при написании клиентских приложений. Сейчас же просто примите к сведенью, что она есть.

    Перейдем к формированию объектов.

    XML объекты

        Важнейшей структурной единицей любого DTM-сервиса являются XML-объекты. XML-объект - это место, в котором хранятся некоторые данные. XML-объект может включать в себя как простые переменные-члены так и другое XML-объекты. По требованию родительского объекта XML-объект может записывать, считывать или создавать данные. Для хранения данных XML-объект использует узлы XML(проще говоря, ноды).

        Классы реализующие интерфейс IXMLObject отвечают за запись/считывание/создание данных в нодах XML.

    Интерфейс IXMLObject имеет следующие свойства и методы:
  • SaveChanges

  • XMLCreate
  • XMLLoad
  • XMLNode - Property Get/Set
        Начнем по порядку. Метод SaveChanges сохраняет данные, XMLCreate создает данные, а XMLLoad считывает данные. Свойство XMLNode указывает, в какой нод должно производится считывание/создание/сохранение. Вот и весь интерфейс. Всего четыре метода. И именно эти четыре метода, пожалуй являются чуть ли не самыми главными в DTM.

    Пример класса, реализующего IXMLObject

        Вернемся к нашему примеру с телефонной книгой. В нашей книге будет такой XML-объект - запись_в_телефонной_книге, или TelefonRecord. TelefonRecord содержит две переменны члена - номер телефона и имя владельца этого номера. Вот код этого класса:

    Implements IXMLObject
    Dim node As MSXML2.IXMLDOMNode
    'CLASS_SUBITEMS{{
    'ПОМЕСТИТЕ ЗДЕСЬ операторы объявления всех элементов класса
    Public PhoneNumber As String
    Public PersonName As String
    '}}CLASS_SUBITEMS
    
    '==================================
    '=======This class DTMItems========
    '==================================
    'CLASS_SUBITEMS_PROPS{{
    'ПОМЕСТИТЕ ЗДЕСЬ операторы Propertu Let/Get для всех элементов класса
    '}}'CLASS_SUBITEMS_PROPS
    
    '==================================
    '=====IXMLObject implementation====
    '==================================
    Private Sub IXMLObject_SaveChanges()
    'CLASS_SUBITEMS_SAVE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для сохранения всех элементов класса
    'Напр.: Call SaveNode_str(node, "name", Name)
    Call SaveNode_str(node, "phone_number", PhoneNumber)
    Call SaveNode_str(node, "person_name", PersonName)
    '}}CLASS_SUBITEMS_SAVE
    End Sub
    
    Private Sub IXMLObject_XMLLoad()
    'CLASS_SUBITEMS_LOAD{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для инициализации и загрузки всех элементов класса
    'Напр.: Call LoadNode_str(node, "name", Name)
    Call LoadNode_str(node, "phone_number", PhoneNumber)
    Call LoadNode_str(node, "person_name", PersonName)
    '}}CLASS_SUBITEMS_LOAD
    End Sub
    
    Private Sub IXMLObject_XMLCreate()
    'CLASS_SUBITEMS_CREATE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для инициализации и создания всех элементов класса
    'Напр.: Call CreateNode_obj(node, "obj_name", obj_var)
    '}}CLASS_SUBITEMS_CREATE
    End Sub
    
    Private Property Set IXMLObject_XMLNode(RHS As MSXML2.IXMLDOMNode)
    Set node = RHS
    End Property
    Private Property Get IXMLObject_XMLNode() As MSXML2.IXMLDOMNode
    Set IXMLObject_XMLNode = node
    End Property
    

        Обратите особое снимание на подкрашенные строки кода. Все кроме них - это стандартный код XML-объекта. Эти шесть подкрашенных строк - это то, что делает этот XML-объект записью в телефонной книге. Обратите внимание, что для каждой переменной-члена в нащем классе существует три строки:

    1. Объявление переменной в блоке CLASS_SUBITEMS
    2. Сохранение значения в блоке CLASS_SUBITEMS_SAVE
    3. Загрузка значения в блоке CLASS_SUBITEMS_LOAD

        Создание значения, как отмечалось выше, требуется только для типа obj.
    Кроме этих трех блоков, Вы должны обнаружить еще два. Остановимся немного на них:

  • CLASS_SUBITEMS_PROPS - если Вам нужно проследить изменение данных клиентом, вы можете объявить переменные-члены как private (с приставкой m_), и затем добавить операторы Property в этот блок.
  • CLASS_SUBITEMS_CREATE - если некоторые из ваших переменных-членов имеют тип данных obj они должны инициализироваться в этой процедуре.
    XML коллекции

        Из всех XML-объектов, пожалуй, следует особо выделить XML-коллекции. XML-коллекция - это особый случай XML-объектов. Ни каких специальных интерфейсов они не реализуют(кроме описанного выше IXMLObject), а отличаются они от прочих XML-объектов тем, что у них имеется произвольное количество дочерних нодов. Все дочерние ноды в коллекции имеют одно и тоже имя(пока рассмотрим только однотипные коллекции). Проще говоря, относитесь к коллекции в DTM, как к простой коллекции бейсика (класс Collection).
        Для упрощения однотипных операций в XMLExt определен класс XMLCollection, содержащий все основные свойства и методы. Вам, в большинстве случаев, требуется только вызывать их из своей программы.

    Пример класса, реализующего IXMLObject и являющегося XML-коллекцией

        Ну-ка, придумайте, где бы можно было использовать коллекции в нашем примере - телефонной книге. Для ответа на этот вопрос, достаточно вспомнить, где в нашем примере используется набор(коллекция) каких-то элементов. Правильно - набор_записей_телефонной_книги. Вспомните, у нас уже есть класс TelefonRecord, который характеризует только ОДНУ запись. А ведь в телефонной книге их может быть огромное количество. Для решения этой проблемы мы создадим класс TelefonRecords. Этот класс будет иметь следующие свойства и методы:

  • AddTelefonRecord
  • TelefonRecord(index) - Property get
  • RemoveTelefonRecord(index)
  • ClearTelefonRecord
  • CountTelefonRecord
        Если вы знакомы с коллекциями в VB, то вы без труда разберетесь в назначении этих свойств. Осталось только напомнить, что данная коллекция, помимо динамического добавления/удаления элементов может также сохранять/загружать/создавать данные.
    Вот пример нашего класса TelefonRecords:

    Implements IXMLObject
    Dim WithEvents mColTelefonRecord As XMLCollection
    
    Private Sub Class_Initialize()
    Set mColTelefonRecord = New XMLCollection
    mColTelefonRecord.tagName = "phone"
    End Sub
    
    Public Function AddTelefonRecord() As TelefonRecord
    Set AddTelefonRecord = mColTelefonRecord.Add
    End Function
    
    Public Property Get TelefonRecord(ByVal Index As Long) As TelefonRecord
    Set TelefonRecord = mColTelefonRecord(Index)
    End Property
    
    Public Sub RemoveTelefonRecord(ByVal Index As Long)
    mColTelefonRecord.Remove Index
    End Sub
    
    Public Sub ClearTelefonRecord()
    mColTelefonRecord.Clear
    End Sub
    
    Public Function CountTelefonRecord() As Long
    CountTelefonRecord = mColTelefonRecord.Count
    End Function
    
    '==================================
    '=====IXMLObject implementation====
    '==================================
    Private Sub IXMLObject_SaveChanges()
    mColTelefonRecord.SaveAll
    End Sub
    
    Private Sub IXMLObject_XMLLoad()
    mColTelefonRecord.XMLLoad
    End Sub
    
    Private Sub IXMLObject_XMLCreate()
    End Sub
    
    Private Property Set IXMLObject_XMLNode(RHS As MSXML2.IXMLDOMNode)
    Set mColTelefonRecord.XMLNode = RHS
    End Property
    Private Property Get IXMLObject_XMLNode() As MSXML2.IXMLDOMNode
    Set IXMLObject_XMLNode = mColTelefonRecord.XMLNode
    End Property
    
    Private Sub mColTelefonRecord_NeedToAdd(obj As DANAProgManXMLExt.IXMLObject)
    Set obj = New TelefonRecord
    End Sub
    

        Вы удивитесь, что в коде листинга нету подкрашенных областей и комментариев. Ничего удивительного - комментарии тут не нужны. Ибо создать XML-коллекцию гораздо проще, чем XML-объект. Вы просто вставляете в модуль класса код из шаблона, а потом, используя диалоговое окно "Find and Replace" в VB(Ctrl+F) заменяете в коде слово Some на название коллекционируемого класса(в нашем случае - TelefonRecord). И еще, заменяете (в Class_Initialize) строку TagName, нужным Вам именем тега для объекта(в нашем случае - phone).

    Модель данных

    В понимании DTM, 60% работы программиста заключается в создании модели данных.

    Модель данных - это описание иерархии данных, иерархии объектов и иерархии нодов, а также того, в какой зависимости они находятся друг от друга.
    Иерархия данных - это описание зависимости обрабатываемых данных друг от друга. В DTM подразумеваеться зависимость элементов только по схеме "дерева".
    Иерархия объектов - это описание COM-классов, используемых в нашей модели данных.
    Иерархия нодов - это описание XML-документа, в котором сохраняются данные нашей модели.

    На рисунки приведены все три иерархии для нашего объекта:

    Иерархия данных Иерархия объектов Иерархия нодов

    Теперь объединим все эти три иерархии в общую модель:

    Модель данных

        Смысл использования модели данный в том, чтобы показать какие данные где располагаются, их описание, имена классов и переменных-членов, и имена нодов, где эти данные расположены.

    IFileInputOutput и его сходство с IXMLObject

        Как ранее отмечалось, интерфейс IFileInputOutput служит для записи/считывания в/из файла. Кроме того, как очевидно, в IFileInputOutput также могут храниться какие-то другие данные, как и в IXMLObject. Несмотря на то, что это разные классы, и написать Set IXMLObject=IFileInputOutput вы не можете, функции этих интерфейсов в реализации похожи. Закончим описание модели телефонной книгой самым главным классом.

    Еще один пример класса, реализующего IFileInputOutput

    Вот, собственно наш законченый класс TelefonBook:

    Implements IFileInputOutput
    Dim mXML As MSXML2.DOMDocument, mfName As String, mfc As FileContentType, _
    mRootNode As MSXML2.IXMLDOMNode
    Private Const FILE_CTYPE = "DANA telefon book data file"
    Private Const FILE_ROOTNODE = "TELBOOK"
    
    'CLASS_SUBITEMS{{
    'ПОМЕСТИТЕ ЗДЕСЬ операторы объявления всех элементов класса
    Dim mTelefonRecords As TelefonRecords
    '}}CLASS_SUBITEMS
    
    '==================================
    '=======This class DTMItems========
    '==================================
    'CLASS_SUBITEMS_PROPS{{
    'ПОМЕСТИТЕ ЗДЕСЬ операторы Propertu Let/Get для всех элементов класса
    Public Property Get TelefonRecords() As TelefonRecords
    Set TelefonRecords = mTelefonRecords
    End Property
    '}}'CLASS_SUBITEMS_PROPS
    
    '==================================
    '==IFileInputOutput implementation=
    '==================================
    Private Sub IFileInputOutput_CloseFile()
    'CLASS_SUBITEMS_CLOSE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для уничтожения всех элементов класса
    Set mTelefonRecords = Nothing
    '}}CLASS_SUBITEMS_CLOSE
    Set mRootNode = Nothing
    Set mXML = Nothing
    mfName = ""
    End Sub
    
    Private Sub IFileInputOutput_CreateFile()
    Set mXML = New MSXML2.DOMDocument
    mfc.ContentType = FILE_CTYPE
    mfc.ContentVersion = "1.0"
    Call self_CreateFile(mfc, mXML, FILE_ROOTNODE, mRootNode)
    'CLASS_SUBITEMS_CREATE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для инициализации и создания всех элементов класса
    Set mTelefonRecords = New TelefonRecords
    CreateNode_obj mRootNode, "phones", mTelefonRecords
    '}}CLASS_SUBITEMS_CREATE
    mfName = ""
    End Sub
    
    Private Property Get IFileInputOutput_FileContentType() As DANAProgManXMLExt.FileContentType
    IFileInputOutput_FileContentType = mfc
    End Property
    
    Private Property Get IFileInputOutput_FileName() As String
    IFileInputOutput_FileName = mfName
    End Property
    
    Private Sub IFileInputOutput_ReadFile(ByVal afName As String)
    Set mXML = New MSXML2.DOMDocument If self_ReadFile(Me, mXML, FILE_ROOTNODE, afName,_
     mRootNode) <> srfOK Then
    IFileInputOutput_CloseFile
    Exit Sub
    End If
    'CLASS_SUBITEMS_LOAD{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для инициализации и загрузки всех элементов класса
    Set mTelefonRecords = New TelefonRecords
    LoadNode_obj mRootNode, "phones", mTelefonRecords
    '}}CLASS_SUBITEMS_LOAD
    mfName = afName
    End Sub
    
    Private Function IFileInputOutput_SetFileContentType(NewVal As _
    DANAProgManXMLExt.FileContentType) As Byte
    If NewVal.ContentType = FILE_CTYPE And NewVal.ContentVersion = "1.0" Then
    mfc = NewVal
    IFileInputOutput_SetFileContentType = 1
    Else
    IFileInputOutput_SetFileContentType = 0
    End If
    End Function
    
    Private Sub IFileInputOutput_WriteFile(ByVal afName As String)
    'CLASS_SUBITEMS_SAVE{{
    'ПОМЕСТИТЕ ЗДЕСЬ код для сохранения всех элементов класса
    SaveNode_obj mRootNode, "phones", mTelefonRecords
    '}}CLASS_SUBITEMS_SAVE
    self_WriteFile mXML, afName
    mfName = afName
    End Sub


       
    Этот класс завершает наш проект - Телефонная книга. Теперь нам осталось лишь собрать все классы воедино и получить то, что нам нужно, а именно - DLL для работами с файлами данный телефонной книги. Исходник проекта Вы можете скачать в начале статьи. К этому примеру также прилагается исходник программы-клиента. Изучите их оба, и мы надеемся, что эта статья поможет Вам в понимании модели DTM.
     


    Автор: Velin
    Для использования технологии в коммерческих целях необходимо получить лицензию. Для этого обращайтесь на info@danasoft.ru.

    * См. в архиве с исходным кодом к статье.